WICKET-5819 Support for HTML 5 media tags (audio / video)

Simplify PartWriterCallback by using BoundedInputStream from commons-io.
Add an additional test case with bigger range sizes


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/a1d0df29
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/a1d0df29
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/a1d0df29

Branch: refs/heads/master
Commit: a1d0df298447247fa901cdee26caf6ae4a727c2d
Parents: 4a36aa7
Author: Martin Tzvetanov Grigorov <mgrigo...@apache.org>
Authored: Fri Mar 27 21:25:17 2015 +0200
Committer: Martin Tzvetanov Grigorov <mgrigo...@apache.org>
Committed: Mon Mar 30 21:59:15 2015 +0300

----------------------------------------------------------------------
 .../request/resource/PartWriterCallback.java    | 79 +++++++++++++-------
 .../resource/PackageResourceReferenceTest.java  | 56 ++++++++++++++
 .../request/resource/resource_gt_4096.txt       |  1 +
 3 files changed, 108 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/a1d0df29/wicket-core/src/main/java/org/apache/wicket/request/resource/PartWriterCallback.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/request/resource/PartWriterCallback.java
 
b/wicket-core/src/main/java/org/apache/wicket/request/resource/PartWriterCallback.java
index c0c7a63..5fe8185 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/request/resource/PartWriterCallback.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/request/resource/PartWriterCallback.java
@@ -20,28 +20,47 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.apache.commons.io.input.BoundedInputStream;
 import org.apache.wicket.protocol.http.servlet.ResponseIOException;
 import org.apache.wicket.request.resource.AbstractResource.WriteCallback;
 import org.apache.wicket.request.resource.IResource.Attributes;
+import org.apache.wicket.util.io.IOUtils;
 import org.apache.wicket.util.io.Streams;
+import org.apache.wicket.util.lang.Args;
 
 /**
  * Used to read a part of an input stream and writes it to the output stream 
of the response taken
- * from attributes of the writeData method.
+ * from attributes in {@link 
#writeData(org.apache.wicket.request.resource.IResource.Attributes)}  method.
  *
  * @author Tobias Soloschenko
- *
  */
 public class PartWriterCallback extends WriteCallback
 {
+       /**
+        * The input stream to read from
+        */
        private final InputStream inputStream;
 
+       /**
+        * The total length to read if {@link #endbyte} is not specified
+        */
        private final Long contentLength;
 
-       private final Long startbyte;
+       /**
+        * The byte to start reading from. If omitted then the input stream 
will be read
+        * from its beginning
+        */
+       private Long startbyte;
 
+       /**
+        * The end byte to read from the {@link #inputStream}.
+        * If omitted then the input stream will be read till its end
+        */
        private Long endbyte;
 
+       /**
+        * The size of the buffer that is used for the copying of the data
+        */
        private int bufferSize;
 
 
@@ -51,12 +70,12 @@ public class PartWriterCallback extends WriteCallback
         * Reads a part of the given input stream. If the startbyte parameter 
is not null the number of
         * bytes are skipped till the stream is read. If the endbyte is not 
null the stream is read till
         * endbyte, else to the end of the whole stream. If startbyte and 
endbyte is null the whole
-        * stream is read.
+        * stream is copied.
         *
         * @param inputStream
-        *            the input stream to be read
-        * @param the
-        *            content length
+        *            the input stream to read from
+        * @param contentLength
+        *            content length of the input stream. Ignored if 
<em>endByte</em> is specified
         * @param startbyte
         *            the start position to read from (if not null the number 
of bytes are skipped till
         *            the stream is read)
@@ -68,7 +87,7 @@ public class PartWriterCallback extends WriteCallback
                Long endbyte)
        {
                this.inputStream = inputStream;
-               this.contentLength = contentLength;
+               this.contentLength = Args.notNull(contentLength, 
"contentLength");
                this.startbyte = startbyte;
                this.endbyte = endbyte;
        }
@@ -97,6 +116,12 @@ public class PartWriterCallback extends WriteCallback
                                {
                                        inputStream.skip(startbyte);
                                }
+                               else
+                               {
+                                       // If no start byte has been given set 
it to 0
+                                       // which means no bytes has been skipped
+                                       startbyte = 0L;
+                               }
 
                                // If there are no end bytes given read the 
whole stream till the end
                                if (endbyte == null || 
Long.valueOf(-1).equals(endbyte))
@@ -104,36 +129,34 @@ public class PartWriterCallback extends WriteCallback
                                        endbyte = contentLength;
                                }
 
-                               // The read bytes in the current buffer
-                               int readBytes;
+                               BoundedInputStream boundedInputStream = null;
+                               try
+                               {
+                                       // Stream is going to be read from the 
starting point next to the skipped bytes
+                                       // till the end byte computed by the 
range between startbyte / endbyte
+                                       boundedInputStream = new 
BoundedInputStream(inputStream, endbyte - startbyte);
 
-                               // The total bytes read
-                               long totalBytes = 0;
+                                       // The original input stream is going 
to be closed by the end of the request
+                                       // so set propagate close to false
+                                       
boundedInputStream.setPropagateClose(false);
 
-                               while ((readBytes = inputStream.read(buffer)) 
!= -1)
-                               {
-                                       totalBytes += readBytes;
+                                       // The read bytes in the current buffer
+                                       int readBytes;
 
-                                       // Check if the end byte is reached
-                                       if (endbyte - totalBytes < 0)
+                                       while ((readBytes = 
boundedInputStream.read(buffer)) != -1)
                                        {
-                                               // calculate the bytes left to 
be read in the current buffer
-                                               // can be casted to int, 
because the the previous chunks are
-                                               // subtracted - so it can't 
exceed buffer size
-                                               int leftBytesToBeRead = 
(int)(totalBytes - startbyte) -
-                                                       (int)(totalBytes - 
endbyte);
-                                               outputStream.write(buffer, 0, 
leftBytesToBeRead);
-                                               break;
-                                       }
-                                       else
-                                       {
-                                               // If the end byte is not 
reached read the full buffer
                                                outputStream.write(buffer, 0, 
readBytes);
                                        }
                                }
+                               finally
+                               {
+                                       
IOUtils.closeQuietly(boundedInputStream);
+                               }
                        }
                        else
                        {
+                               // No range has been given so copy the content
+                               // from input stream to the output stream
                                Streams.copy(inputStream, outputStream, 
getBufferSize());
                        }
                }

http://git-wip-us.apache.org/repos/asf/wicket/blob/a1d0df29/wicket-core/src/test/java/org/apache/wicket/request/resource/PackageResourceReferenceTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/request/resource/PackageResourceReferenceTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/request/resource/PackageResourceReferenceTest.java
index a58a2c9..4057674 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/request/resource/PackageResourceReferenceTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/request/resource/PackageResourceReferenceTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.wicket.request.resource;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Locale;
 
 import org.apache.wicket.Application;
@@ -28,6 +30,7 @@ import 
org.apache.wicket.request.resource.AbstractResource.ContentRangeType;
 import org.apache.wicket.request.resource.IResource.Attributes;
 import org.apache.wicket.request.resource.ResourceReference.UrlAttributes;
 import org.apache.wicket.response.ByteArrayResponse;
+import org.apache.wicket.util.io.IOUtils;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -275,6 +278,59 @@ public class PackageResourceReferenceTest extends 
WicketTestCase
 
        /**
         * See WICKET-5819 - Media tags
+        *
+        * @throws IOException
+        */
+       @Test
+       public void testContentRangeLarge() throws IOException
+       {
+               InputStream resourceAsStream = null;
+               try
+               {
+                       resourceAsStream = 
PackageResourceReference.class.getResourceAsStream("resource_gt_4096.txt");
+                       String content = new 
String(IOUtils.toByteArray(resourceAsStream));
+
+                       // Check buffer comprehensive range request
+                       String bytes4094_4106 = 
makeRangeRequestToBigResource("bytes=4094-4106");
+                       assertEquals(12, bytes4094_4106.length());
+                       assertEquals("River Roller", bytes4094_4106);
+
+                       // Check buffer exceeding range request
+                       String bytes1000_5000 = 
makeRangeRequestToBigResource("bytes=1000-5000");
+                       assertEquals(4000, bytes1000_5000.length());
+                       assertEquals(content.substring(1000, 5000), 
bytes1000_5000);
+
+                       // Check buffer exceeding range request until end of 
content
+                       String bytes1000_end = 
makeRangeRequestToBigResource("bytes=1000-");
+                       assertEquals(4529, bytes1000_end.length());
+                       assertEquals(content.substring(1000, content.length()), 
bytes1000_end);
+
+                       // Check complete range request
+                       assertEquals(content.length(), 
makeRangeRequestToBigResource("bytes=-").length());
+               }
+               finally
+               {
+                       IOUtils.closeQuietly(resourceAsStream);
+               }
+       }
+
+       private String makeRangeRequestToBigResource(String range)
+       {
+               ResourceReference reference = new 
PackageResourceReference(scope, "resource_gt_4096.txt",
+                       null, null, null);
+
+               ByteArrayResponse byteResponse = new ByteArrayResponse();
+
+               Request request = tester.getRequestCycle().getRequest();
+               MockHttpServletRequest mockHttpServletRequest = 
(MockHttpServletRequest)request.getContainerRequest();
+               mockHttpServletRequest.setHeader("range", range);
+               Attributes mockAttributes = new Attributes(request, 
byteResponse);
+               reference.getResource().respond(mockAttributes);
+               return new String(byteResponse.getBytes());
+       }
+
+       /**
+        * See WICKET-5819 - Media tags
         */
        @Test
        public void testContentRangeHeaders()

http://git-wip-us.apache.org/repos/asf/wicket/blob/a1d0df29/wicket-core/src/test/java/org/apache/wicket/request/resource/resource_gt_4096.txt
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/request/resource/resource_gt_4096.txt
 
b/wicket-core/src/test/java/org/apache/wicket/request/resource/resource_gt_4096.txt
new file mode 100644
index 0000000..2b0c235
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/request/resource/resource_gt_4096.txt
@@ -0,0 +1 @@
+HTTP Server Abdera Accumulo ACE ActiveMQ Airavata Allura Ambari Ant Any23 APR 
Archiva Aries Avro Axis Bigtop Bloodhound Buildr BVal Camel Cassandra Cayenne 
Chemistry Chukwa Clerezza CloudStack Cocoon Commons Continuum Cordova CouchDB 
Creadur Crunch cTAKES Curator CXF DB Deltacloud DeltaSpike DirectMemory 
Directory Empire-db Etch Falcon Felix Flex Flume Forrest Geronimo Giraph Gora 
Gump Hadoop Hama HBase Helix Hive HttpComponents Isis Jackrabbit James jclouds 
Jena JMeter JSPWiki jUDDI Kafka Karaf Knox Lenya Libcloud Logging Lucene 
Lucene.Net Lucy Mahout ManifoldCF Marmotta Maven Mesos MINA MRUnit MyFaces 
Nutch ODE OFBiz Olingo Oltu Onami OODT Oozie Open Climate Workbench OpenJPA 
OpenMeetings OpenNLP OpenOffice OpenWebBeans PDFBox Perl Pig Pivot POI Portals 
Qpid Rave River Roller Santuario ServiceMix Shindig Shiro SIS Sling 
SpamAssassin Spark Sqoop Stanbol STeVe Storm Struts Subversion Synapse Syncope 
Tajo Tapestry Tcl Tez Thrift Tika Tiles Tomcat TomEE Traffic Server Turbine 
Tuscany 
 UIMA VCL Velocity VXQuery Web Services Whirr Wicket Wink Wookie Xalan Xerces 
XMLBeans XML Graphics ZooKeeper HTTP Server Abdera Accumulo ACE ActiveMQ 
Airavata Allura Ambari Ant Any23 APR Archiva Aries Avro Axis Bigtop Bloodhound 
Buildr BVal Camel Cassandra Cayenne Chemistry Chukwa Clerezza CloudStack Cocoon 
Commons Continuum Cordova CouchDB Creadur Crunch cTAKES Curator CXF DB 
Deltacloud DeltaSpike DirectMemory Directory Empire-db Etch Falcon Felix Flex 
Flume Forrest Geronimo Giraph Gora Gump Hadoop Hama HBase Helix Hive 
HttpComponents Isis Jackrabbit James jclouds Jena JMeter JSPWiki jUDDI Kafka 
Karaf Knox Lenya Libcloud Logging Lucene Lucene.Net Lucy Mahout ManifoldCF 
Marmotta Maven Mesos MINA MRUnit MyFaces Nutch ODE OFBiz Olingo Oltu Onami OODT 
Oozie Open Climate Workbench OpenJPA OpenMeetings OpenNLP OpenOffice 
OpenWebBeans PDFBox Perl Pig Pivot POI Portals Qpid Rave River Roller Santuario 
ServiceMix Shindig Shiro SIS Sling SpamAssassin Spark Sqoop Stanbol STeVe Storm 
Struts Su
 bversion Synapse Syncope Tajo Tapestry Tcl Tez Thrift Tika Tiles Tomcat TomEE 
Traffic Server Turbine Tuscany UIMA VCL Velocity VXQuery Web Services Whirr 
Wicket Wink Wookie Xalan Xerces XMLBeans XML Graphics ZooKeeper HTTP Server 
Abdera Accumulo ACE ActiveMQ Airavata Allura Ambari Ant Any23 APR Archiva Aries 
Avro Axis Bigtop Bloodhound Buildr BVal Camel Cassandra Cayenne Chemistry 
Chukwa Clerezza CloudStack Cocoon Commons Continuum Cordova CouchDB Creadur 
Crunch cTAKES Curator CXF DB Deltacloud DeltaSpike DirectMemory Directory 
Empire-db Etch Falcon Felix Flex Flume Forrest Geronimo Giraph Gora Gump Hadoop 
Hama HBase Helix Hive HttpComponents Isis Jackrabbit James jclouds Jena JMeter 
JSPWiki jUDDI Kafka Karaf Knox Lenya Libcloud Logging Lucene Lucene.Net Lucy 
Mahout ManifoldCF Marmotta Maven Mesos MINA MRUnit MyFaces Nutch ODE OFBiz 
Olingo Oltu Onami OODT Oozie Open Climate Workbench OpenJPA OpenMeetings 
OpenNLP OpenOffice OpenWebBeans PDFBox Perl Pig Pivot POI Portals Qpid Rave Riv
 er Roller Santuario ServiceMix Shindig Shiro SIS Sling SpamAssassin Spark 
Sqoop Stanbol STeVe Storm Struts Subversion Synapse Syncope Tajo Tapestry Tcl 
Tez Thrift Tika Tiles Tomcat TomEE Traffic Server Turbine Tuscany UIMA VCL 
Velocity VXQuery Web Services Whirr Wicket Wink Wookie Xalan Xerces XMLBeans 
XML Graphics ZooKeeper HTTP Server Abdera Accumulo ACE ActiveMQ Airavata Allura 
Ambari Ant Any23 APR Archiva Aries Avro Axis Bigtop Bloodhound Buildr BVal 
Camel Cassandra Cayenne Chemistry Chukwa Clerezza CloudStack Cocoon Commons 
Continuum Cordova CouchDB Creadur Crunch cTAKES Curator CXF DB Deltacloud 
DeltaSpike DirectMemory Directory Empire-db Etch Falcon Felix Flex Flume 
Forrest Geronimo Giraph Gora Gump Hadoop Hama HBase Helix Hive HttpComponents 
Isis Jackrabbit James jclouds Jena JMeter JSPWiki jUDDI Kafka Karaf Knox Lenya 
Libcloud Logging Lucene Lucene.Net Lucy Mahout ManifoldCF Marmotta Maven Mesos 
MINA MRUnit MyFaces Nutch ODE OFBiz Olingo Oltu Onami OODT Oozie Open Climate W
 orkbench OpenJPA OpenMeetings OpenNLP OpenOffice OpenWebBeans PDFBox Perl Pig 
Pivot POI Portals Qpid Rave River Roller Santuario ServiceMix Shindig Shiro SIS 
Sling SpamAssassin Spark Sqoop Stanbol STeVe Storm Struts Subversion Synapse 
Syncope Tajo Tapestry Tcl Tez Thrift Tika Tiles Tomcat TomEE Traffic Server 
Turbine Tuscany UIMA VCL Velocity VXQuery Web Services Whirr Wicket Wink Wookie 
Xalan Xerces XMLBeans XML Graphics ZooKeeper HTTP Server Abdera Accumulo ACE 
ActiveMQ Airavata Allura Ambari Ant Any23 APR Archiva Aries Avro Axis Bigtop 
Bloodhound Buildr BVal Camel Cassandra Cayenne Chemistry Chukwa Clerezza 
CloudStack Cocoon Commons Continuum Cordova CouchDB Creadur Crunch cTAKES 
Curator CXF DB Deltacloud DeltaSpike DirectMemory Directory Empire-db Etch 
Falcon Felix Flex Flume Forrest Geronimo Giraph Gora Gump Hadoop Hama HBase 
Helix Hive HttpComponents Isis Jackrabbit James jclouds Jena JMeter JSPWiki 
jUDDI Kafka Karaf Knox Lenya Libcloud Logging Lucene Lucene.Net Lucy Mahout Ma
 nifoldCF Marmotta Maven Mesos MINA MRUnit MyFaces Nutch ODE OFBiz Olingo Oltu 
Onami OODT Oozie Open Climate Workbench OpenJPA OpenMeetings OpenNLP OpenOffice 
OpenWebBeans PDFBox Perl Pig Pivot POI Portals Qpid Rave River Roller Santuario 
ServiceMix Shindig Shiro SIS Sling SpamAssassin Spark Sqoop Stanbol STeVe Storm 
Struts Subversion Synapse Syncope Tajo Tapestry Tcl Tez Thrift Tika Tiles 
Tomcat TomEE Traffic Server Turbine Tuscany UIMA VCL Velocity VXQuery Web 
Services Whirr Wicket Wink Wookie Xalan Xerces XMLBeans XML Graphics ZooKeeper
\ No newline at end of file

Reply via email to