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.
5import json
6import optparse
7import os
8import sys
9import time
10import traceback
11from build import generate_deps_js_contents as deps_generator
12from build import generate_template_contents as template_generator
13
14import SocketServer
15import SimpleHTTPServer
16import BaseHTTPServer
17
18DEFAULT_PORT = 8003
19DEPS_CHECK_DELAY = 30
20
21toplevel_dir = os.path.abspath(os.path.dirname(__file__))
22src_dir = os.path.join(toplevel_dir, 'src')
23test_data_dir = os.path.join(toplevel_dir, 'test_data')
24
25class 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
142class 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
148def 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
160if __name__ == '__main__':
161  os.chdir(toplevel_dir)
162  sys.exit(Main(sys.argv[1:]))
163