View Javadoc
1   package org.andromda.cartridges.jsf.renderkit;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.OutputStream;
6   
7   import javax.faces.component.UIComponent;
8   import javax.faces.context.FacesContext;
9   import javax.faces.render.Renderer;
10  import javax.servlet.http.HttpServletResponse;
11  
12  import org.andromda.cartridges.jsf.component.BinaryFile;
13  import org.apache.commons.lang.StringUtils;
14  
15  
16  /**
17   * A custom renderer for rendering a binary file.
18   *
19   * @author Chad Brandon
20   */
21  public class BinaryFileRenderer
22      extends Renderer
23  {
24      /**
25       * Gets the current response instance.
26       *
27       * @return the current response.
28       */
29      private HttpServletResponse getResponse(final FacesContext context)
30      {
31          return (HttpServletResponse)context.getExternalContext().getResponse();
32      }
33  
34      private static final int BUFFER_SIZE = 4096;
35  
36      @Override
37      public void encodeBegin(
38          FacesContext context,
39          UIComponent component)
40          throws IOException
41      {
42          final BinaryFile fileComponent = (BinaryFile)component;
43          if (fileComponent.isRendered())
44          {
45              final HttpServletResponse response = this.getResponse(context);
46              final OutputStream stream = response.getOutputStream();
47  
48              // - reset the response to clear out any any headers (i.e. so
49              //   the user doesn't get "unable to open..." when using IE.)
50              response.reset();
51              final String fileName = fileComponent.getFileName();
52              if (fileComponent.isPrompt() && fileName != null && fileName.trim().length() > 0)
53              {
54                  response.addHeader(
55                      "Content-disposition",
56                      "attachment; filename=\"" + fileName + '"');
57              }
58  
59              Object value = fileComponent.getValue();
60              final String contentType = fileComponent.getContentType();
61              // - for IE we need to set the content type, content length and buffer size and
62              //   then the flush the response right away because it seems as if there is any lag time
63              //   IE just displays a blank page. With mozilla based clients reports display correctly regardless.
64              if (StringUtils.isNotBlank(contentType))
65              {
66                  response.setContentType(contentType);
67              }
68              final String encoding = fileComponent.getEncoding();
69              if (StringUtils.isNotBlank(encoding))
70              {
71                  response.setCharacterEncoding(encoding);
72              }
73              if (value != null)
74              {
75                  if (value instanceof String)
76                  {
77                      value = StringUtils.isNotBlank(encoding) ? ((String)value).getBytes(encoding) : ((String)value).getBytes();
78                  }
79                  if (value instanceof byte[])
80                  {
81                      byte[] file = (byte[])value;
82                      response.setBufferSize(file.length);
83                      response.setContentLength(file.length);
84                      response.flushBuffer();
85                      stream.write(file);
86                  }
87                  else if (value instanceof InputStream)
88                  {
89                      final InputStream report = (InputStream)value;
90                      final byte[] buffer = new byte[BUFFER_SIZE];
91                      response.setBufferSize(BUFFER_SIZE);
92                      response.flushBuffer();
93                      for (int ctr = 0; (ctr = report.read(buffer)) > 0;)
94                      {
95                          stream.write(buffer, 0, ctr);
96                      }
97                      stream.flush();
98                  }
99              }
100         }
101     }
102 
103     @Override
104     public void encodeEnd(
105         final FacesContext context,
106         final UIComponent component)
107         throws IOException
108     {
109         final BinaryFile fileComponent = (BinaryFile)component;
110         if (fileComponent.isRendered())
111         {
112             final HttpServletResponse response = this.getResponse(context);
113             final OutputStream stream = response.getOutputStream();
114             stream.flush();
115             stream.close();
116         }
117     }
118 }