incubator-wookie-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From scot...@apache.org
Subject svn commit: r1160014 - in /incubator/wookie/trunk: WebContent/WEB-INF/web.xml src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java src/org/apache/wookie/flatpack/FlatpackController.java
Date Sun, 21 Aug 2011 17:22:02 GMT
Author: scottbw
Date: Sun Aug 21 17:22:01 2011
New Revision: 1160014

URL: http://svn.apache.org/viewvc?rev=1160014&view=rev
Log:
Added a very basic file download function for responding to a GET request for an exported
widget instance ("flatpack"). This gets around various configuration issues associated with
"default servlets" on different servlet containers (e.g. Jetty vs Tomcat) - see WOOKIE-231
and WOOKIE-182. Limitations in terms of security have also been noted in the code comments,
and associated functional tests were also updated. Note that requests for flatpacks are now
targeted at GET /flatpack/{id} and not /exports/{id}, but that exported files are still physically
located in /exports - however the /exports folder itself is not published. 

Modified:
    incubator/wookie/trunk/WebContent/WEB-INF/web.xml
    incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java
    incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java

Modified: incubator/wookie/trunk/WebContent/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/WebContent/WEB-INF/web.xml?rev=1160014&r1=1160013&r2=1160014&view=diff
==============================================================================
--- incubator/wookie/trunk/WebContent/WEB-INF/web.xml (original)
+++ incubator/wookie/trunk/WebContent/WEB-INF/web.xml Sun Aug 21 17:22:01 2011
@@ -135,7 +135,6 @@
 		<url-pattern>/updates/*</url-pattern>
 	</servlet-mapping>
 	
-	
 	<servlet>
 		<description></description>
 		<display-name>Flatpack</display-name>
@@ -149,10 +148,6 @@
 		<servlet-name>Flatpack</servlet-name>
 		<url-pattern>/flatpack/*</url-pattern>
 	</servlet-mapping>
-	<servlet-mapping>
- 		<servlet-name>default</servlet-name>
- 		<url-pattern>/export/*</url-pattern>	
-	</servlet-mapping>
 
 	<servlet>
 		<description></description>

Modified: incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java?rev=1160014&r1=1160013&r2=1160014&view=diff
==============================================================================
--- incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java
(original)
+++ incubator/wookie/trunk/src-tests/org/apache/wookie/tests/functional/FlatpackControllerTest.java
Sun Aug 21 17:22:01 2011
@@ -33,7 +33,7 @@ public class FlatpackControllerTest exte
   private static final String TEST_FLATPACK_SERVICE_URL_VALID = TEST_SERVER_LOCATION
       + "flatpack";
   private static final String TEST_EXPORT_SERVICE_URL_VALID = TEST_SERVER_LOCATION
-      + "export";
+      + "flatpack";
   private static final String TEST_WIDGET_ID_JQM = "http://wookie.apache.org/widgets/freeder";
   private static String test_id_key = "";
 
@@ -81,12 +81,7 @@ public class FlatpackControllerTest exte
     GetMethod get = new GetMethod(TEST_EXPORT_SERVICE_URL_VALID);
     client.executeMethod(get);
     int code = get.getStatusCode();
-    if (code != 404) {
-      String html = get.getResponseBodyAsString();
-      System.out.println(html);
-      assertEquals(html.length(), 0);
-    }
-
+    assertEquals(403, code);
   }
 
   /**

Modified: incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java?rev=1160014&r1=1160013&r2=1160014&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java (original)
+++ incubator/wookie/trunk/src/org/apache/wookie/flatpack/FlatpackController.java Sun Aug
21 17:22:01 2011
@@ -13,7 +13,10 @@
  */
 package org.apache.wookie.flatpack;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.URL;
 
@@ -27,6 +30,7 @@ import org.apache.wookie.beans.IWidgetIn
 import org.apache.wookie.controller.Controller;
 import org.apache.wookie.controller.WidgetInstancesController;
 import org.apache.wookie.exceptions.InvalidParametersException;
+import org.apache.wookie.exceptions.ResourceNotFoundException;
 import org.apache.wookie.exceptions.UnauthorizedAccessException;
 import org.apache.wookie.helpers.WidgetKeyManager;
 
@@ -36,6 +40,8 @@ import org.apache.wookie.helpers.WidgetK
  * This class provides a controller front end for the FlatpackFactory class, enabling the
export of Widget Instances via a HTTP POST request.
  * 
  * POST /flatpack/ {params: api_key, instance_params OR id_key} creates a new W3C Widget
package (.wgt) with an opaque file name for the specified widget instance, and returns the
download URL. 
+ * GET /flatpack/id.wgt download a previously created flatpack
+ * 
  * If an invalid API key is supplied, a 401 error code is returned. If no instance can be
found, or the parameters supplied are invalid, a 400 error code is returned.
  */
 public class FlatpackController extends Controller {
@@ -43,16 +49,131 @@ public class FlatpackController extends 
 	private static final long serialVersionUID = 2907712805939515004L;
 	static Logger _logger = Logger.getLogger(FlatpackController.class.getName());	
 
+	/* (non-Javadoc)
+   * @see org.apache.wookie.controller.Controller#show(java.lang.String, javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse)
+   */
 	/**
-	 * Deny access to the listing of the flatpack folder
+	 * Downloads a previously generated export file.
+	 * 
+	 * <p><b>Note:</b> currently there is no authentication for this method,
which relies solely
+	 * on the hard-to-guess exported widget name. </p>
+	 * 
+	 * <p>For the future we may want to:</p>
+	 * 
+	 * <ul>
+	 * <li> require an access token of some kind before allowing download. </ul>
+	 * <li> delete exported widgets after they have been downloaded. </ul>
+	 * <li> delete exported widgets at a set period after they have been created. </ul>
+	 * </ul>
 	 */
-	@Override
-	protected void doGet(HttpServletRequest request,
-			HttpServletResponse response) throws ServletException, IOException {
-		response.sendError(HttpServletResponse.SC_FORBIDDEN);
-	}
+  @Override
+  protected void show(String resourceId, HttpServletRequest request,
+      HttpServletResponse response) throws ResourceNotFoundException,
+      UnauthorizedAccessException, IOException {
+    
+    //
+    // If there is no resource part of the requested path, or the request is not for a ".wgt"
file, return a 404 immediately
+    //
+    if (resourceId == null || resourceId.trim().length() == 0 || !resourceId.endsWith(".wgt"))
{
+      throw new ResourceNotFoundException();
+    }
+    
+    //
+    // Get the file path for the requested item
+    //
+    String requestedPackageFilePath = request.getSession().getServletContext().getRealPath(FlatpackFactory.DEFAULT_FLATPACK_FOLDER+"/"+resourceId);
+    
+    //
+    // Get the widget package corresponding to the path, and throw a 404 if it doesn't exist
+    //
+    File widgetPackage = new File(requestedPackageFilePath);
+    if (!widgetPackage.exists()){
+      throw new ResourceNotFoundException();
+    }
+    
+    //
+    // Log the download and the IP used
+    //
+    _logger.info("exported widget package " + resourceId + " downloaded; IP:" + request.getRemoteAddr());
+    
+    //
+    // Set the content-type of the response to application/widget, which
+    // is the standard MIME type for widgets.
+    //
+    final String contentType = "application/widget";
+    
+    //
+    // Set buffer size of response to 10k
+    //
+    final int bufferSize = 10240;
+    
+    //
+    // Initialize the response
+    //
+    response.reset();
+    response.setBufferSize(bufferSize);
+    response.setContentType(contentType);
+    response.setHeader("Content-Length", String.valueOf(widgetPackage.length()));
+    
+    //
+    // We can override the browser default behaviour to force it to open a save dialog box;
+    // however at least Opera will treat this as a Widget package and do something smarter,
and
+    // perhaps other browsers may do so in future, so leaving this commented out.
+    //
+    //response.setHeader("Content-Disposition", "attachment; filename=\"" + widgetPackage.getName()
+ "\"");
+
+    //
+    // Prepare streams
+    //
+    BufferedInputStream input = null;
+    BufferedOutputStream output = null;
+
+    //
+    // Send the file
+    //
+    try {
+      
+        //
+        // Open streams
+        //
+        input = new BufferedInputStream(new FileInputStream(widgetPackage), bufferSize);
+        output = new BufferedOutputStream(response.getOutputStream(), bufferSize);
+
+        //
+        // Stream the file to the response
+        //
+        byte[] buffer = new byte[bufferSize];
+        int length;
+        while ((length = input.read(buffer)) > 0) {
+            output.write(buffer, 0, length);
+        }
+        
+    } finally {
+      
+        //
+        // Close streams
+        //
+        output.close();
+        input.close();
+    }
+
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.wookie.controller.Controller#index(javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse)
+   */
+  /**
+   * Deny access to the listing of the flatpack folder
+   */
+  @Override
+  protected void index(HttpServletRequest request, HttpServletResponse response)
+      throws UnauthorizedAccessException, IOException {
+    response.sendError(HttpServletResponse.SC_FORBIDDEN);
+  }
 
-	/**
+
+
+  /**
 	 * We override the default POST method from Controller as we need to return the package
URL in the Response to the client
 	 */
 	@Override



Mime
View raw message