1 #!/usr/bin/env python 2 3 """The clang static analyzer results viewer. 4 """ 5 6 import sys 7 import posixpath 8 import thread 9 import time 10 import urllib 11 import webbrowser 12 13 # How long to wait for server to start. 14 kSleepTimeout = .05 15 kMaxSleeps = int(60 / kSleepTimeout) 16 17 # Default server parameters 18 19 kDefaultHost = '127.0.0.1' 20 kDefaultPort = 8181 21 kMaxPortsToTry = 100 22 23 ### 24 25 def url_is_up(url): 26 try: 27 o = urllib.urlopen(url) 28 except IOError: 29 return False 30 o.close() 31 return True 32 33 def start_browser(port, options): 34 import urllib, webbrowser 35 36 url = 'http://%s:%d'%(options.host, port) 37 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 56 def run(port, options, root): 57 import ScanView 58 try: 59 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) 64 httpd.serve_forever() 65 except KeyboardInterrupt: 66 pass 67 68 def 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 77 def main(): 78 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( 85 '--port', dest="port", default=None, type="int", 86 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.") 90 parser.add_option("--auto-reload", dest="autoReload", default=False, 91 action="store_true", 92 help="Automatically update module for each request.") 93 parser.add_option("--no-browser", dest="startBrowser", default=True, 94 action="store_false", 95 help="Don't open a webbrowser on startup.") 96 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)') 99 (options, args) = parser.parse_args() 100 101 if len(args) != 1: 102 parser.error('No results directory specified.') 103 root, = args 104 105 # 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 109 # 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 123 # Kick off thread to wait for server and start web browser, if 124 # requested. 125 if options.startBrowser: 126 t = thread.start_new_thread(start_browser, (port,options)) 127 128 run(port, options, root) 129 130 if __name__ == '__main__': 131 main() 132