blob: fb27da698882e7447906a24f70e99fcc627f1d57 [file] [log] [blame]
Daniel Dunbare33d3682008-09-19 23:32:11 +00001#!/usr/bin/env python
2
3"""The clang static analyzer results viewer.
4"""
5
6import sys
Daniel Dunbare673c082008-09-22 01:42:08 +00007import posixpath
Daniel Dunbare33d3682008-09-19 23:32:11 +00008import thread
9import time
10import urllib
11import webbrowser
12
13# How long to wait for server to start.
14kSleepTimeout = .05
Ted Kremenek305d2d22009-05-04 19:02:41 +000015kMaxSleeps = int(60 / kSleepTimeout)
Daniel Dunbare33d3682008-09-19 23:32:11 +000016
17# Default server parameters
18
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000019kDefaultHost = '127.0.0.1'
Daniel Dunbare33d3682008-09-19 23:32:11 +000020kDefaultPort = 8181
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000021kMaxPortsToTry = 100
Daniel Dunbare33d3682008-09-19 23:32:11 +000022
23###
24
25def url_is_up(url):
26 try:
27 o = urllib.urlopen(url)
28 except IOError:
29 return False
30 o.close()
31 return True
32
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000033def start_browser(port, options):
Daniel Dunbare33d3682008-09-19 23:32:11 +000034 import urllib, webbrowser
35
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000036 url = 'http://%s:%d'%(options.host, port)
Daniel Dunbare33d3682008-09-19 23:32:11 +000037
38 # Wait for server to start...
39 if options.debug:
40 sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
41 sys.stderr.flush()
42 for i in range(kMaxSleeps):
43 if url_is_up(url):
44 break
45 if options.debug:
46 sys.stderr.write('.')
47 sys.stderr.flush()
48 time.sleep(kSleepTimeout)
49 else:
50 print >>sys.stderr,'WARNING: Unable to detect that server started.'
51
52 if options.debug:
53 print >>sys.stderr,'%s: Starting webbrowser...' % sys.argv[0]
54 webbrowser.open(url)
55
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000056def run(port, options, root):
Daniel Dunbare33d3682008-09-19 23:32:11 +000057 import ScanView
58 try:
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000059 print 'Starting scan-view at: http://%s:%d'%(options.host,
60 port)
61 print ' Use Ctrl-C to exit.'
62 httpd = ScanView.create_server((options.host, port),
63 options, root)
Daniel Dunbare33d3682008-09-19 23:32:11 +000064 httpd.serve_forever()
65 except KeyboardInterrupt:
66 pass
67
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000068def port_is_open(port):
69 import SocketServer
70 try:
71 t = SocketServer.TCPServer((kDefaultHost,port),None)
72 except:
73 return False
74 t.server_close()
75 return True
76
77def main():
Daniel Dunbare33d3682008-09-19 23:32:11 +000078 from optparse import OptionParser
79 parser = OptionParser('usage: %prog [options] <results directory>')
80 parser.set_description(__doc__)
81 parser.add_option(
82 '--host', dest="host", default=kDefaultHost, type="string",
83 help="Host interface to listen on. (default=%s)" % kDefaultHost)
84 parser.add_option(
Daniel Dunbar7ad535d2008-09-22 02:53:12 +000085 '--port', dest="port", default=None, type="int",
Daniel Dunbare33d3682008-09-19 23:32:11 +000086 help="Port to listen on. (default=%s)" % kDefaultPort)
87 parser.add_option("--debug", dest="debug", default=0,
88 action="count",
89 help="Print additional debugging information.")
Daniel Dunbarcb028b02008-09-21 20:34:58 +000090 parser.add_option("--auto-reload", dest="autoReload", default=False,
91 action="store_true",
92 help="Automatically update module for each request.")
Daniel Dunbare33d3682008-09-19 23:32:11 +000093 parser.add_option("--no-browser", dest="startBrowser", default=True,
94 action="store_false",
95 help="Don't open a webbrowser on startup.")
Daniel Dunbarf6a415f2008-09-24 17:59:41 +000096 parser.add_option("--allow-all-hosts", dest="onlyServeLocal", default=True,
97 action="store_false",
98 help='Allow connections from any host (access restricted to "127.0.0.1" by default)')
Daniel Dunbare33d3682008-09-19 23:32:11 +000099 (options, args) = parser.parse_args()
100
101 if len(args) != 1:
Daniel Dunbare673c082008-09-22 01:42:08 +0000102 parser.error('No results directory specified.')
Daniel Dunbare33d3682008-09-19 23:32:11 +0000103 root, = args
104
Daniel Dunbare673c082008-09-22 01:42:08 +0000105 # Make sure this directory is in a reasonable state to view.
106 if not posixpath.exists(posixpath.join(root,'index.html')):
107 parser.error('Invalid directory, analysis results not found!')
108
Daniel Dunbar7ad535d2008-09-22 02:53:12 +0000109 # Find an open port. We aren't particularly worried about race
110 # conditions here. Note that if the user specified a port we only
111 # use that one.
112 if options.port is not None:
113 port = options.port
114 else:
115 for i in range(kMaxPortsToTry):
116 if port_is_open(kDefaultPort + i):
117 port = kDefaultPort + i
118 break
119 else:
120 parser.error('Unable to find usable port in [%d,%d)'%(kDefaultPort,
121 kDefaultPort+kMaxPortsToTry))
122
Daniel Dunbare33d3682008-09-19 23:32:11 +0000123 # Kick off thread to wait for server and start web browser, if
124 # requested.
125 if options.startBrowser:
Daniel Dunbar7ad535d2008-09-22 02:53:12 +0000126 t = thread.start_new_thread(start_browser, (port,options))
Daniel Dunbare33d3682008-09-19 23:32:11 +0000127
Daniel Dunbar7ad535d2008-09-22 02:53:12 +0000128 run(port, options, root)
Daniel Dunbare33d3682008-09-19 23:32:11 +0000129
130if __name__ == '__main__':
131 main()