Save This Page
Home » struts-2.0.11.2-src » org.apache » struts2 » dispatcher » [javadoc | source]
    1   /*
    2    * $Id: StreamResult.java 570513 2007-08-28 18:14:00Z jholmes $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    *  http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   20    */
   21   package org.apache.struts2.dispatcher;
   22   
   23   import java.io.InputStream;
   24   import java.io.OutputStream;
   25   
   26   import javax.servlet.http.HttpServletResponse;
   27   
   28   import org.apache.commons.logging.Log;
   29   import org.apache.commons.logging.LogFactory;
   30   
   31   import com.opensymphony.xwork2.ActionInvocation;
   32   
   33   /**
   34    * <!-- START SNIPPET: description -->
   35    *
   36    * A custom Result type for sending raw data (via an InputStream) directly to the
   37    * HttpServletResponse. Very useful for allowing users to download content.
   38    *
   39    * <!-- END SNIPPET: description -->
   40    * <p/>
   41    * <b>This result type takes the following parameters:</b>
   42    *
   43    * <!-- START SNIPPET: params -->
   44    *
   45    * <ul>
   46    *
   47    * <li><b>contentType</b> - the stream mime-type as sent to the web browser
   48    * (default = <code>text/plain</code>).</li>
   49    *
   50    * <li><b>contentLength</b> - the stream length in bytes (the browser displays a
   51    * progress bar).</li>
   52    *
   53    * <li><b>contentDispostion</b> - the content disposition header value for
   54    * specifing the file name (default = <code>inline</code>, values are typically
   55    * <i>filename="document.pdf"</i>.</li>
   56    *
   57    * <li><b>inputName</b> - the name of the InputStream property from the chained
   58    * action (default = <code>inputStream</code>).</li>
   59    *
   60    * <li><b>bufferSize</b> - the size of the buffer to copy from input to output
   61    * (default = <code>1024</code>).</li>
   62    *
   63    * </ul>
   64    *
   65    * <!-- END SNIPPET: params -->
   66    *
   67    * <b>Example:</b>
   68    *
   69    * <pre><!-- START SNIPPET: example -->
   70    * &lt;result name="success" type="stream"&gt;
   71    *   &lt;param name="contentType"&gt;image/jpeg&lt;/param&gt;
   72    *   &lt;param name="inputName"&gt;imageStream&lt;/param&gt;
   73    *   &lt;param name="contentDisposition"&gt;filename="document.pdf"&lt;/param&gt;
   74    *   &lt;param name="bufferSize"&gt;1024&lt;/param&gt;
   75    * &lt;/result&gt;
   76    * <!-- END SNIPPET: example --></pre>
   77    *
   78    */
   79   public class StreamResult extends StrutsResultSupport {
   80   
   81       private static final long serialVersionUID = -1468409635999059850L;
   82   
   83       protected static final Log log = LogFactory.getLog(StreamResult.class);
   84   
   85       public static final String DEFAULT_PARAM = "inputName";
   86   
   87       protected String contentType = "text/plain";
   88       protected String contentLength;
   89       protected String contentDisposition = "inline";
   90       protected String inputName = "inputStream";
   91       protected InputStream inputStream;
   92       protected int bufferSize = 1024;
   93   
   94       public StreamResult() {
   95           super();
   96       }
   97   
   98       public StreamResult(InputStream in) {
   99           this.inputStream = in;
  100       }
  101   
  102       /**
  103        * @return Returns the bufferSize.
  104        */
  105       public int getBufferSize() {
  106           return (bufferSize);
  107       }
  108   
  109       /**
  110        * @param bufferSize The bufferSize to set.
  111        */
  112       public void setBufferSize(int bufferSize) {
  113           this.bufferSize = bufferSize;
  114       }
  115   
  116       /**
  117        * @return Returns the contentType.
  118        */
  119       public String getContentType() {
  120           return (contentType);
  121       }
  122   
  123       /**
  124        * @param contentType The contentType to set.
  125        */
  126       public void setContentType(String contentType) {
  127           this.contentType = contentType;
  128       }
  129   
  130       /**
  131        * @return Returns the contentLength.
  132        */
  133       public String getContentLength() {
  134           return contentLength;
  135       }
  136   
  137       /**
  138        * @param contentLength The contentLength to set.
  139        */
  140       public void setContentLength(String contentLength) {
  141           this.contentLength = contentLength;
  142       }
  143   
  144       /**
  145        * @return Returns the Content-disposition header value.
  146        */
  147       public String getContentDisposition() {
  148           return contentDisposition;
  149       }
  150   
  151       /**
  152        * @param contentDisposition the Content-disposition header value to use.
  153        */
  154       public void setContentDisposition(String contentDisposition) {
  155           this.contentDisposition = contentDisposition;
  156       }
  157   
  158       /**
  159        * @return Returns the inputName.
  160        */
  161       public String getInputName() {
  162           return (inputName);
  163       }
  164   
  165       /**
  166        * @param inputName The inputName to set.
  167        */
  168       public void setInputName(String inputName) {
  169           this.inputName = inputName;
  170       }
  171   
  172       /**
  173        * @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
  174        */
  175       protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
  176   
  177           OutputStream oOutput = null;
  178   
  179           try {
  180               if (inputStream == null) {
  181                   // Find the inputstream from the invocation variable stack
  182                   inputStream = (InputStream) invocation.getStack().findValue(conditionalParse(inputName, invocation));
  183               }
  184   
  185               if (inputStream == null) {
  186                   String msg = ("Can not find a java.io.InputStream with the name [" + inputName + "] in the invocation stack. " +
  187                       "Check the <param name=\"inputName\"> tag specified for this action.");
  188                   log.error(msg);
  189                   throw new IllegalArgumentException(msg);
  190               }
  191   
  192               // Find the Response in context
  193               HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
  194   
  195               // Set the content type
  196               oResponse.setContentType(conditionalParse(contentType, invocation));
  197   
  198               // Set the content length
  199               if (contentLength != null) {
  200                   String _contentLength = conditionalParse(contentLength, invocation);
  201                   int _contentLengthAsInt = -1;
  202                   try {
  203                       _contentLengthAsInt = Integer.parseInt(_contentLength);
  204                       if (_contentLengthAsInt >= 0) {
  205                           oResponse.setContentLength(_contentLengthAsInt);
  206                       }
  207                   }
  208                   catch(NumberFormatException e) {
  209                       log.warn("failed to recongnize "+_contentLength+" as a number, contentLength header will not be set", e);
  210                   }
  211               }
  212   
  213               // Set the content-disposition
  214               if (contentDisposition != null) {
  215                   oResponse.addHeader("Content-disposition", conditionalParse(contentDisposition, invocation));
  216               }
  217   
  218               // Get the outputstream
  219               oOutput = oResponse.getOutputStream();
  220   
  221               if (log.isDebugEnabled()) {
  222                   log.debug("Streaming result [" + inputName + "] type=[" + contentType + "] length=[" + contentLength +
  223                       "] content-disposition=[" + contentDisposition + "]");
  224               }
  225   
  226               // Copy input to output
  227               log.debug("Streaming to output buffer +++ START +++");
  228               byte[] oBuff = new byte[bufferSize];
  229               int iSize;
  230               while (-1 != (iSize = inputStream.read(oBuff))) {
  231                   oOutput.write(oBuff, 0, iSize);
  232               }
  233               log.debug("Streaming to output buffer +++ END +++");
  234   
  235               // Flush
  236               oOutput.flush();
  237           }
  238           finally {
  239               if (inputStream != null) inputStream.close();
  240               if (oOutput != null) oOutput.close();
  241           }
  242       }
  243   
  244   }

Save This Page
Home » struts-2.0.11.2-src » org.apache » struts2 » dispatcher » [javadoc | source]