1 #!/usr/bin/env python 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 import json 6 import optparse 7 import os 8 import sys 9 import time 10 import traceback 11 from build import generate_deps_js_contents as deps_generator 12 from build import generate_template_contents as template_generator 13 14 import SocketServer 15 import SimpleHTTPServer 16 import BaseHTTPServer 17 18 DEFAULT_PORT = 8003 19 DEPS_CHECK_DELAY = 30 20 21 toplevel_dir = os.path.abspath(os.path.dirname(__file__)) 22 src_dir = os.path.join(toplevel_dir, 'src') 23 test_data_dir = os.path.join(toplevel_dir, 'test_data') 24 25 class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): 26 def __init__(self, *args, **kwargs): 27 SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) 28 29 def send_response(self, code, message=None): 30 SimpleHTTPServer.SimpleHTTPRequestHandler.send_response(self, code, message) 31 if code == 200: 32 self.send_header('Cache-Control', 'no-cache') 33 34 def do_GET_json_tests(self): 35 def is_test(x): 36 basename = os.path.basename(x) 37 if basename.startswith('.'): 38 return False 39 40 if basename.endswith('_test.js'): 41 return True 42 return False 43 44 test_filenames = [] 45 for dirpath, dirnames, filenames in os.walk(src_dir): 46 for f in filenames: 47 x = os.path.join(dirpath, f) 48 y = '/' + os.path.relpath(x, toplevel_dir) 49 if is_test(y): 50 test_filenames.append(y) 51 52 test_filenames.sort() 53 54 tests_as_json = json.dumps(test_filenames) 55 56 self.send_response(200) 57 self.send_header('Content-Type', 'application/json') 58 self.send_header('Content-Length', len(tests_as_json)) 59 self.end_headers() 60 self.wfile.write(tests_as_json) 61 62 def do_GET_example_files(self): 63 data_files = [] 64 for dirpath, dirnames, filenames in os.walk(test_data_dir): 65 for f in filenames: 66 data_files.append(f) 67 68 data_files.sort() 69 files_as_json = json.dumps(data_files) 70 71 self.send_response(200) 72 self.send_header('Content-Type', 'application/json') 73 self.send_header('Content-Length', len(files_as_json)) 74 self.end_headers() 75 self.wfile.write(files_as_json) 76 77 def do_GET_deps(self): 78 current_time = time.time() 79 if self.server.next_deps_check < current_time: 80 self.log_message('Regenerating ' + self.path) 81 try: 82 self.server.deps = deps_generator.generate_deps_js() 83 except Exception, ex: 84 msg = json.dumps({"details": traceback.format_exc(), 85 "message": ex.message}); 86 self.log_error('While parsing deps: %s', ex.message) 87 self.send_response(500) 88 self.send_header('Content-Type', 'application/json') 89 self.send_header('Cache-Control', 'no-cache') 90 self.send_header('Content-Length', len(msg)) 91 self.end_headers() 92 self.wfile.write(msg) 93 return 94 95 self.server.next_deps_check = current_time + DEPS_CHECK_DELAY 96 97 self.send_response(200) 98 self.send_header('Content-Type', 'application/javascript') 99 self.send_header('Content-Length', len(self.server.deps)) 100 self.end_headers() 101 self.wfile.write(self.server.deps) 102 103 def do_GET_templates(self): 104 templates = template_generator.generate_templates() 105 106 self.send_response(200) 107 self.send_header('Content-Type', 'text/html') 108 self.send_header('Content-Length', len(templates)) 109 self.end_headers() 110 self.wfile.write(templates) 111 112 def do_GET(self): 113 if self.path == '/json/examples': 114 self.do_GET_example_files() 115 return 116 117 if self.path == '/json/tests': 118 self.do_GET_json_tests() 119 return 120 121 if self.path == '/templates': 122 self.do_GET_templates() 123 return 124 125 if self.path == '/deps.js': 126 self.do_GET_deps() 127 return 128 129 return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) 130 131 def log_error(self, format, *args): 132 if self.path == '/favicon.ico': 133 return 134 self.log_message("While processing %s: ", self.path) 135 SimpleHTTPServer.SimpleHTTPRequestHandler.log_error(self, format, *args) 136 137 def log_request(self, code='-', size='-'): 138 # Dont spam the console unless it is important. 139 pass 140 141 142 class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): 143 def __init__(self, *args, **kwargs): 144 BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs) 145 self.next_deps_check = -1 146 self.deps = None 147 148 def Main(args): 149 parser = optparse.OptionParser() 150 parser.add_option('--port', 151 action='store', 152 type='int', 153 default=DEFAULT_PORT, 154 help='Port to serve from') 155 options, args = parser.parse_args() 156 server = Server(('', options.port), Handler) 157 sys.stderr.write("Now running on http://localhost:%i\n" % options.port) 158 server.serve_forever() 159 160 if __name__ == '__main__': 161 os.chdir(toplevel_dir) 162 sys.exit(Main(sys.argv[1:])) 163