diff -r 000000000000 -r 4f2f89ce4247 WebKitTools/TestResultServer/handlers/testfilehandler.py --- /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")