--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKitTools/TestResultServer/handlers/testfilehandler.py Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,221 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import logging
+import urllib
+
+from google.appengine.api import users
+from google.appengine.ext import blobstore
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import blobstore_handlers
+from google.appengine.ext.webapp import template
+
+from model.testfile import TestFile
+
+PARAM_BUILDER = "builder"
+PARAM_DIR = "dir"
+PARAM_FILE = "file"
+PARAM_NAME = "name"
+PARAM_KEY = "key"
+PARAM_TEST_TYPE = "testtype"
+
+
+class DeleteFile(webapp.RequestHandler):
+ """Delete test file for a given builder and name from datastore (metadata) and blobstore (file data)."""
+
+ def get(self):
+ key = self.request.get(PARAM_KEY)
+ builder = self.request.get(PARAM_BUILDER)
+ test_type = self.request.get(PARAM_TEST_TYPE)
+ name = self.request.get(PARAM_NAME)
+
+ logging.debug(
+ "Deleting File, builder: %s, test_type: %s, name: %s, blob key: %s.",
+ builder, test_type, name, key)
+
+ TestFile.delete_file(key, builder, test_type, name, 100)
+
+ # Display file list after deleting the file.
+ self.redirect("/testfile?builder=%s&testtype=%s&name=%s"
+ % (builder, test_type, name))
+
+
+class GetFile(blobstore_handlers.BlobstoreDownloadHandler):
+ """Get file content or list of files for given builder and name."""
+
+ def _get_file_list(self, builder, test_type, name):
+ """Get and display a list of files that matches builder and file name.
+
+ Args:
+ builder: builder name
+ test_type: type of the test
+ name: file name
+ """
+
+ files = TestFile.get_files(builder, test_type, name, 100)
+ if not files:
+ logging.info("File not found, builder: %s, test_type: %s, name: %s.",
+ builder, test_type, name)
+ self.response.out.write("File not found")
+ return
+
+ template_values = {
+ "admin": users.is_current_user_admin(),
+ "builder": builder,
+ "test_type": test_type,
+ "name": name,
+ "files": files,
+ }
+ self.response.out.write(template.render("templates/showfilelist.html",
+ template_values))
+
+ def _get_file_content(self, builder, test_type, name):
+ """Return content of the file that matches builder and file name.
+
+ Args:
+ builder: builder name
+ test_type: type of the test
+ name: file name
+ """
+
+ files = TestFile.get_files(builder, test_type, name, 1)
+ if not files:
+ logging.info("File not found, builder: %s, test_type: %s, name: %s.",
+ builder, test_type, name)
+ return
+
+ blob_key = files[0].blob_key
+ blob_info = blobstore.get(blob_key)
+ if blob_info:
+ self.send_blob(blob_info, "text/plain")
+
+ def get(self):
+ builder = self.request.get(PARAM_BUILDER)
+ test_type = self.request.get(PARAM_TEST_TYPE)
+ name = self.request.get(PARAM_NAME)
+ dir = self.request.get(PARAM_DIR)
+
+ logging.debug(
+ "Getting files, builder: %s, test_type: %s, name: %s.",
+ builder, test_type, name)
+
+ # If parameter "dir" is specified or there is no builder or filename
+ # specified in the request, return list of files, otherwise, return
+ # file content.
+ if dir or not builder or not name:
+ return self._get_file_list(builder, test_type, name)
+ else:
+ return self._get_file_content(builder, test_type, name)
+
+
+class GetUploadUrl(webapp.RequestHandler):
+ """Get an url for uploading file to blobstore. A special url is required for each blobsotre upload."""
+
+ def get(self):
+ upload_url = blobstore.create_upload_url("/testfile/upload")
+ logging.info("Getting upload url: %s.", upload_url)
+ self.response.out.write(upload_url)
+
+
+class Upload(blobstore_handlers.BlobstoreUploadHandler):
+ """Upload file to blobstore."""
+
+ def post(self):
+ uploaded_files = self.get_uploads("file")
+ if not uploaded_files:
+ return self._upload_done([("Missing upload file field.")])
+
+ builder = self.request.get(PARAM_BUILDER)
+ if not builder:
+ for blob_info in uploaded_files:
+ blob_info.delete()
+
+ return self._upload_done([("Missing builder parameter in upload request.")])
+
+ test_type = self.request.get(PARAM_TEST_TYPE)
+
+ logging.debug(
+ "Processing upload request, builder: %s, test_type: %s.",
+ builder, test_type)
+
+ errors = []
+ for blob_info in uploaded_files:
+ tf = TestFile.update_file(builder, test_type, blob_info)
+ if not tf:
+ errors.append(
+ "Upload failed, builder: %s, test_type: %s, name: %s." %
+ (builder, test_type, blob_info.filename))
+ blob_info.delete()
+
+ return self._upload_done(errors)
+
+ def _upload_done(self, errors):
+ logging.info("upload done.")
+
+ error_messages = []
+ for error in errors:
+ logging.info(error)
+ error_messages.append("error=%s" % urllib.quote(error))
+
+ if error_messages:
+ redirect_url = "/uploadfail?%s" % "&".join(error_messages)
+ else:
+ redirect_url = "/uploadsuccess"
+
+ logging.info(redirect_url)
+ # BlobstoreUploadHandler requires redirect at the end.
+ self.redirect(redirect_url)
+
+
+class UploadForm(webapp.RequestHandler):
+ """Show a form so user can submit a file to blobstore."""
+
+ def get(self):
+ upload_url = blobstore.create_upload_url("/testfile/upload")
+ template_values = {
+ "upload_url": upload_url,
+ }
+ self.response.out.write(template.render("templates/uploadform.html",
+ template_values))
+
+class UploadStatus(webapp.RequestHandler):
+ """Return status of file uploading"""
+
+ def get(self):
+ logging.debug("Update status")
+
+ if self.request.path == "/uploadsuccess":
+ self.response.set_status(200)
+ self.response.out.write("OK")
+ else:
+ errors = self.request.params.getall("error")
+ if errors:
+ messages = "FAIL: " + "; ".join(errors)
+ logging.warning(messages)
+ self.response.set_status(500, messages)
+ self.response.out.write("FAIL")