Author: dklco
Date: Mon Jun 24 15:25:02 2013
New Revision: 1496093

URL: http://svn.apache.org/r1496093
Log:
Fixing SLING-2834: adding support for var and scope variables for including the 
results of a response into a JSP variable

Modified:
    
sling/trunk/bundles/scripting/jsp-taglib/src/main/java/org/apache/sling/scripting/jsp/taglib/IncludeTagHandler.java
    
sling/trunk/bundles/scripting/jsp-taglib/src/main/resources/META-INF/sling.tld

Modified: 
sling/trunk/bundles/scripting/jsp-taglib/src/main/java/org/apache/sling/scripting/jsp/taglib/IncludeTagHandler.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp-taglib/src/main/java/org/apache/sling/scripting/jsp/taglib/IncludeTagHandler.java?rev=1496093&r1=1496092&r2=1496093&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/jsp-taglib/src/main/java/org/apache/sling/scripting/jsp/taglib/IncludeTagHandler.java
 (original)
+++ 
sling/trunk/bundles/scripting/jsp-taglib/src/main/java/org/apache/sling/scripting/jsp/taglib/IncludeTagHandler.java
 Mon Jun 24 15:25:02 2013
@@ -16,15 +16,23 @@
  */
 package org.apache.sling.scripting.jsp.taglib;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.jsp.tagext.BodyContent;
 
+import org.apache.tika.io.IOUtils;
+
 /**
  * The <code>IncludeTagHandler</code> implements the
  * <code>&lt;sling:include&gt;</code> custom tag.
@@ -35,6 +43,8 @@ public class IncludeTagHandler extends A
 
     /** flush argument */
     private boolean flush = false;
+    private String var = null;
+    private Integer scope = PageContext.PAGE_SCOPE;
 
     protected void dispatch(RequestDispatcher dispatcher,
             ServletRequest request, ServletResponse response)
@@ -45,8 +55,22 @@ public class IncludeTagHandler extends A
             // might throw an IOException of course
             pageContext.getOut().flush();
         }
-
-        dispatcher.include(request, response);
+        if (var == null) {
+               dispatcher.include(request, response);
+        } else {
+               String encoding = response.getCharacterEncoding();
+               BufferedServletOutputStream bsops = new 
BufferedServletOutputStream(encoding);
+               try{
+                       CaptureResponseWrapper wrapper = new 
CaptureResponseWrapper((HttpServletResponse) response, bsops);
+                       dispatcher.include(request, wrapper);
+                       if (! wrapper.isBinaryResponse()) {
+                               wrapper.flushBuffer();
+                       pageContext.setAttribute(var, bsops.getBuffer(), scope);
+                       }
+               }finally{
+                       IOUtils.closeQuietly(bsops);
+               }
+        }
     }
 
     public void setPageContext(PageContext pageContext) {
@@ -54,10 +78,174 @@ public class IncludeTagHandler extends A
 
         // init local fields, since tag might be reused
         flush = false;
+        this.var = null;
+        this.scope = PageContext.PAGE_SCOPE;
     }
 
     public void setFlush(boolean flush) {
         this.flush = flush;
     }
-
+    
+    public void setVar(String var) {
+       if (var != null && var.trim().length() > 0) {
+               this.var = var;
+       }
+    }
+    
+    // for tag attribute
+    public void setScope(String scope) {
+       this.scope = validScope(scope);
+    }
+    
+       /**
+        * Gets the int code for a valid scope, must be one of 'page', 
'request',
+        * 'session' or 'application'. If an invalid or no scope is specified 
page
+        * scope is returned.
+        * 
+        * @param scope
+        * @return
+        */
+       private Integer validScope(String scope) {
+               scope = (scope != null && scope.trim().length() > 0 ? 
scope.trim()
+                               .toUpperCase() : null);
+               if (scope == null) {
+                       return PageContext.PAGE_SCOPE;
+               }
+
+               String[] scopes = { "PAGE", "REQUEST", "SESSION", "APPLICATION" 
};
+               Integer[] iaScopes = { PageContext.PAGE_SCOPE,
+                               PageContext.REQUEST_SCOPE, 
PageContext.SESSION_SCOPE,
+                               PageContext.APPLICATION_SCOPE };
+
+               for (int ndx = 0, len = scopes.length; ndx < len; ndx++) {
+                       if (scopes[ndx].equals(scope)) {
+                               return iaScopes[ndx];
+                       }
+               }
+               return PageContext.PAGE_SCOPE;
+    }
+    
+    /**
+     * Extends the HttpServletResponse to wrap the response and capture the 
results.
+     */
+    private static final class CaptureResponseWrapper extends 
HttpServletResponseWrapper {
+               private final String encoding;
+               private final ServletOutputStream ops;
+               private boolean isBinaryResponse = false;
+               private PrintWriter writer = null;
+
+               /**
+                * Construct a new CaptureResponseWrapper.
+                * 
+                * @param response
+                *            the response to wrap
+                * @param ops
+                *            the output stream to write to
+                */
+               CaptureResponseWrapper(HttpServletResponse response,
+                               ServletOutputStream ops) {
+                       super(response);
+                       this.encoding = response.getCharacterEncoding();
+                       this.ops = ops;
+               }
+
+               /**
+                * Returns true if the response is binary.
+                * 
+                * @return
+                */
+       public boolean isBinaryResponse() {
+               return isBinaryResponse;
+       }
+       
+       
+       /*
+        * (non-Javadoc)
+        * @see javax.servlet.ServletResponseWrapper#flushBuffer()
+        */
+       @Override
+               public void flushBuffer() throws IOException {
+               if (isBinaryResponse()) {
+                       getResponse().getOutputStream().flush();
+               } else {
+                       writer.flush();
+               }
+               }
+
+       /*
+        * (non-Javadoc)
+        * @see javax.servlet.ServletResponseWrapper#getOutputStream()
+        */
+               @Override
+       public ServletOutputStream getOutputStream() throws IOException {
+               if (writer != null) {
+                       throw new IOException("'getWriter()' has already been 
invoked for a character data response.");
+               }
+               isBinaryResponse = true;
+               return getResponse().getOutputStream();
+       }
+       
+               /*
+                * (non-Javadoc)
+                * @see javax.servlet.ServletResponseWrapper#getWriter()
+                */
+       @Override
+       public PrintWriter getWriter() throws IOException {
+               if (writer != null) {
+                       return writer;
+               }
+               if (isBinaryResponse) {
+                       throw new IOException("'getOutputStream()' has already 
been invoked for a binary data response.");
+               }
+               writer = new PrintWriter(new OutputStreamWriter(ops, encoding));
+               return writer;
+       }
+       
+    }
+    
+    /**
+     * Extends the ServletOutputStream to capture the results into a byte 
array.
+     */
+    private static final class BufferedServletOutputStream extends 
ServletOutputStream {
+       private final ByteArrayOutputStream baops = new ByteArrayOutputStream();
+       private final String encoding;
+       
+       /**
+        * Constructs a new BufferedServletOutputStream.
+        * 
+        * @param encoding the encoding string
+        */
+       public BufferedServletOutputStream(String encoding) {
+                       this.encoding = encoding;
+               }
+
+               /**
+        * Gets the byte buffer as a string.
+        * 
+        * @return the byte buffer
+                * @throws IOException
+        */
+       public String getBuffer() throws IOException {
+               return baops.toString(encoding);
+       }
+       
+       /*
+        * (non-Javadoc)
+        * @see java.io.OutputStream#close()
+        */
+       @Override
+       public void close() throws IOException {
+               baops.reset();
+               super.close();
+       }
+       
+       /*
+        * (non-Javadoc)
+        * @see java.io.OutputStream#write(int)
+        */
+       @Override
+       public void write(int b) throws IOException {
+               baops.write(b);
+       }
+    }
 }

Modified: 
sling/trunk/bundles/scripting/jsp-taglib/src/main/resources/META-INF/sling.tld
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp-taglib/src/main/resources/META-INF/sling.tld?rev=1496093&r1=1496092&r2=1496093&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/jsp-taglib/src/main/resources/META-INF/sling.tld 
(original)
+++ 
sling/trunk/bundles/scripting/jsp-taglib/src/main/resources/META-INF/sling.tld 
Mon Jun 24 15:25:02 2013
@@ -176,6 +176,24 @@
                        <required>false</required>
                        <rtexprvalue>true</rtexprvalue>
                </attribute>
+        <attribute>
+            <description>
+                If var is specified, what scope to store the variable in
+            </description>
+            <name>scope</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <type>String</type>
+        </attribute>
+        <attribute>
+            <description>
+                Variable name to store the resulting markup into
+            </description>
+            <name>var</name>
+            <required>false</required>
+            <rtexprvalue>false</rtexprvalue>
+            <type>String</type>
+        </attribute>
        </tag>
 
        <tag>


Reply via email to