You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2013/06/24 17:25:02 UTC

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

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>