Author: jbq
Date: Tue Feb 27 15:23:46 2007
New Revision: 512487

URL: http://svn.apache.org/viewvc?view=rev&rev=512487
Log:
Fix WICKET-327: Download link does not set Content-Type and Content-Length 
headers

Adding two methods in WebResponse:

* write(InputStream in)
* detectContentType(RequestCycle requestCycle, String uri)

Added:
    
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadLinkTest.java
    
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.html
    
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.java
Modified:
    
incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/link/DownloadLink.java
    
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebResponse.java
    
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/request/WebExternalResourceRequestTarget.java

Modified: 
incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/link/DownloadLink.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/link/DownloadLink.java?view=diff&rev=512487&r1=512486&r2=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/link/DownloadLink.java
 (original)
+++ 
incubator/wicket/trunk/wicket/src/main/java/wicket/markup/html/link/DownloadLink.java
 Tue Feb 27 15:23:46 2007
@@ -18,15 +18,12 @@
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
 
 import wicket.IRequestTarget;
 import wicket.MarkupContainer;
 import wicket.RequestCycle;
+import wicket.WicketRuntimeException;
 import wicket.protocol.http.WebResponse;
-import wicket.util.io.Streams;
 import wicket.util.string.Strings;
 
 /**
@@ -126,30 +123,13 @@
 
                                try
                                {
-                                       InputStream is = new 
FileInputStream(file);
-                                       try
-                                       {
-                                               Streams.copy(is, 
r.getOutputStream());
-                                       }
-                                       catch (IOException e)
-                                       {
-                                               throw new RuntimeException(e);
-                                       }
-                                       finally
-                                       {
-                                               try
-                                               {
-                                                       is.close();
-                                               }
-                                               catch (IOException e)
-                                               {
-                                                       throw new 
RuntimeException(e);
-                                               }
-                                       }
+                                       r.write(new FileInputStream(file));
+                                       r.setContentLength(file.length());
+                                       r.detectContentType(requestCycle, 
fileName);
                                }
-                               catch (FileNotFoundException e)
+                               catch (Exception e)
                                {
-                                       throw new RuntimeException(e);
+                                       throw new WicketRuntimeException(e);
                                }
                        }
                });

Modified: 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebResponse.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebResponse.java?view=diff&rev=512487&r1=512486&r2=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebResponse.java
 (original)
+++ 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebResponse.java
 Tue Feb 27 15:23:46 2007
@@ -17,17 +17,22 @@
 package wicket.protocol.http;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.URLConnection;
 import java.util.Locale;
 
+import javax.servlet.ServletContext;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import wicket.RequestCycle;
 import wicket.Response;
 import wicket.WicketRuntimeException;
+import wicket.util.io.Streams;
 import wicket.util.string.AppendingStringBuffer;
 import wicket.util.string.Strings;
 import wicket.util.time.Time;
@@ -52,7 +57,7 @@
 
        /** The underlying response object. */
        private final HttpServletResponse httpServletResponse;
-       
+
        /** Is the request an ajax request? */
        private boolean ajax;
 
@@ -201,13 +206,15 @@
                                                log.debug("Redirecting to " + 
url);
                                        }
 
-                                       if (isAjax()) 
+                                       if (isAjax())
                                        {
                                                
httpServletResponse.addHeader("Ajax-Location", url);
 
-                                               // safari chokes on empty 
response. but perhaps this is not the best place?
-                                               
httpServletResponse.getWriter().write(" ");                                     
        
-                                       } else 
+                                               // safari chokes on empty 
response. but perhaps this is
+                                               // not the best place?
+                                               
httpServletResponse.getWriter().write(" ");
+                                       }
+                                       else
                                        {
                                                
httpServletResponse.sendRedirect(url);
                                        }
@@ -402,10 +409,81 @@
        /**
         * Set that the request which matches this response is an ajax request.
         * 
-        * @param ajax True if the request is an ajax request.
+        * @param ajax
+        *            True if the request is an ajax request.
         */
        public void setAjax(boolean ajax)
        {
                this.ajax = ajax;
+       }
+
+       /**
+        * Copies the given input stream to the servlet response
+        * <p>
+        * NOTE Content-Length is not set because it would require to buffer the
+        * whole input stream
+        * </p>
+        * 
+        * @param in
+        *            input stream to copy, will be closed after copy
+        */
+       public void write(InputStream in)
+       {
+               try
+               {
+                       // Copy resource input stream to servlet output stream
+                       Streams.copy(in, 
getHttpServletResponse().getOutputStream());
+               }
+               catch (Exception e)
+               {
+                       throw new WicketRuntimeException(e);
+               }
+               finally
+               {
+                       // NOTE: We only close the InputStream. The servlet
+                       // container should close the output stream.
+                       try
+                       {
+                               in.close();
+                       }
+                       catch (IOException e)
+                       {
+                               throw new WicketRuntimeException(e);
+                       }
+               }
+       }
+
+       /**
+        * Sets the Content-Type header with servlet-context-defined 
content-types
+        * (application's web.xml or servlet container's configuration), and 
fall
+        * back to system or JVM-defined (FileNameMap) content types.
+        * 
+        * @param requestCycle
+        * @param uri
+        *            Resource name to be analyzed to detect MIME type
+        * 
+        * @see ServletContext#getMimeType(String)
+        * @see URLConnection#getFileNameMap()
+        */
+       public void detectContentType(RequestCycle requestCycle, String uri)
+       {
+               // Configure response with content type of resource
+               final ServletContext context = 
((WebApplication)requestCycle.getApplication())
+                               .getServletContext();
+               // First look for user defined content-type in web.xml
+               String contentType = context.getMimeType(uri);
+
+               // If not found, fall back to
+               // FileResourceStream.getContentType() that looks into
+               // system or JVM content types
+               if (contentType == null)
+               {
+                       contentType = 
URLConnection.getFileNameMap().getContentTypeFor(uri);
+               }
+
+               if (contentType != null)
+               {
+                       setContentType(contentType);
+               }
        }
 }

Modified: 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/request/WebExternalResourceRequestTarget.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/request/WebExternalResourceRequestTarget.java?view=diff&rev=512487&r1=512486&r2=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/request/WebExternalResourceRequestTarget.java
 (original)
+++ 
incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/request/WebExternalResourceRequestTarget.java
 Tue Feb 27 15:23:46 2007
@@ -31,7 +31,6 @@
 import wicket.protocol.http.WebApplication;
 import wicket.protocol.http.WebRequestCycle;
 import wicket.protocol.http.WebResponse;
-import wicket.util.io.Streams;
 
 /**
  * Request target that is not a Wicket resource. For example, such a resource
@@ -86,23 +85,10 @@
                        {
                                // TODO check can this really by done by any 
kind of url??
                                // Is this class really only used internally 
with a relative url to a resource in the servlet context.
-                               // Set content type. 
-                               String contentType = context.getMimeType(url);
-                               if(contentType != null)
-                               {
-                                       webResponse.setContentType(contentType);
-                               }                               
-                               try
-                               {
-                                       // Copy resource input stream to 
servlet output stream
-                                       Streams.copy(in, 
webResponse.getHttpServletResponse().getOutputStream());
-                               }
-                               finally
-                               {
-                                       // NOTE: We only close the InputStream. 
The servlet
-                                       // container should close the output 
stream.
-                                       in.close();
-                               }
+                               webResponse.write(in);
+                               // Set content type
+                               webResponse.detectContentType(requestCycle, 
url);
+                               // FIXME do we need to call 
webResponse.setContentLength()?
                        }
                        else
                        {
@@ -169,4 +155,4 @@
        {
                return "[WebExternalResourceRequestTarget@" + hashCode() + " " 
+ url + "]";
        }
-}
\ No newline at end of file
+}

Added: 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadLinkTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadLinkTest.java?view=auto&rev=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadLinkTest.java
 (added)
+++ 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadLinkTest.java
 Tue Feb 27 15:23:46 2007
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package wicket.markup.html.link;
+
+import wicket.WicketTestCase;
+import wicket.protocol.http.MockHttpServletResponse;
+import wicket.protocol.http.MockServletContext;
+
+/**
+ * Tests DownloadLink
+ * 
+ * @author <a href="mailto:[EMAIL PROTECTED]">Jean-Baptiste Quenot</a>
+ */
+public class DownloadLinkTest extends WicketTestCase
+{
+       private static final String APPLICATION_X_CUSTOM = 
"application/x-custom";
+
+       public DownloadLinkTest(String name)
+       {
+               super(name);
+       }
+
+       public void testTextDownloadLink()
+       {
+               tester.startPage(DownloadPage.class);
+               tester.clickLink(DownloadPage.TEXT_DOWNLOAD_LINK);
+               assertEquals("text/plain", getContentType());
+               assertEquals(0, getContentLength());
+       }
+
+       public void testPdfDownloadLink()
+       {
+               tester.startPage(DownloadPage.class);
+               tester.clickLink(DownloadPage.PDF_DOWNLOAD_LINK);
+               assertEquals("application/pdf", getContentType());
+               assertEquals(DownloadPage.HELLO_WORLD.length(), 
getContentLength());
+       }
+
+       public void testCustomTypeDownloadLink()
+       {
+               tester.startPage(DownloadPage.class);
+               
((MockServletContext)tester.getApplication().getServletContext()).addMimeType("custom",
+                               APPLICATION_X_CUSTOM);
+               tester.clickLink(DownloadPage.CUSTOM_DOWNLOAD_LINK);
+               assertEquals(APPLICATION_X_CUSTOM, getContentType());
+       }
+
+       private String getContentType()
+       {
+               return 
((MockHttpServletResponse)tester.getWicketResponse().getHttpServletResponse())
+                               .getHeader("Content-Type");
+       }
+
+       private int getContentLength()
+       {
+               return 
Integer.parseInt(((MockHttpServletResponse)tester.getWicketResponse()
+                               
.getHttpServletResponse()).getHeader("Content-Length"));
+       }
+}

Added: 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.html
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.html?view=auto&rev=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.html
 (added)
+++ 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.html
 Tue Feb 27 15:23:46 2007
@@ -0,0 +1,7 @@
+<html>
+       <body bgcolor="white">
+               <span wicket:id="textDownload"></span>
+               <span wicket:id="pdfDownload"></span>
+               <span wicket:id="customDownload"></span>
+       </body>
+</html>

Added: 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.java?view=auto&rev=512487
==============================================================================
--- 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.java
 (added)
+++ 
incubator/wicket/trunk/wicket/src/test/java/wicket/markup/html/link/DownloadPage.java
 Tue Feb 27 15:23:46 2007
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package wicket.markup.html.link;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import wicket.markup.html.WebPage;
+
+public class DownloadPage extends WebPage
+{
+       public static final String HELLO_WORLD = "Hello, World!";
+       public static final String TEXT_DOWNLOAD_LINK = "textDownload";
+       public static final String PDF_DOWNLOAD_LINK = "pdfDownload";
+       public static final String CUSTOM_DOWNLOAD_LINK = "customDownload";
+
+       /**
+        * 
+        */
+       private static final long serialVersionUID = 1L;
+
+       public DownloadPage() throws IOException
+       {
+               File textFile = File.createTempFile("Download", ".txt");
+               new DownloadLink(this, TEXT_DOWNLOAD_LINK, textFile);
+
+               File pdfFile = File.createTempFile("Download", ".pdf");
+               FileWriter writer = new FileWriter(pdfFile);
+               writer.write(HELLO_WORLD);
+               writer.close();
+               new DownloadLink(this, PDF_DOWNLOAD_LINK, pdfFile);
+
+               File customFile = File.createTempFile("Download", ".custom");
+               new DownloadLink(this, CUSTOM_DOWNLOAD_LINK, customFile);
+       }
+}


Reply via email to