1*e5dd7070Spatrick#!/usr/bin/env python 2*e5dd7070Spatrick 3*e5dd7070Spatrickfrom __future__ import print_function 4*e5dd7070Spatrick 5*e5dd7070Spatrick"""The clang static analyzer results viewer. 6*e5dd7070Spatrick""" 7*e5dd7070Spatrick 8*e5dd7070Spatrickimport sys 9*e5dd7070Spatrickimport imp 10*e5dd7070Spatrickimport os 11*e5dd7070Spatrickimport posixpath 12*e5dd7070Spatrickimport threading 13*e5dd7070Spatrickimport time 14*e5dd7070Spatricktry: 15*e5dd7070Spatrick from urllib.request import urlopen 16*e5dd7070Spatrickexcept ImportError: 17*e5dd7070Spatrick from urllib2 import urlopen 18*e5dd7070Spatrickimport webbrowser 19*e5dd7070Spatrick 20*e5dd7070Spatrick# How long to wait for server to start. 21*e5dd7070SpatrickkSleepTimeout = .05 22*e5dd7070SpatrickkMaxSleeps = int(60 / kSleepTimeout) 23*e5dd7070Spatrick 24*e5dd7070Spatrick# Default server parameters 25*e5dd7070Spatrick 26*e5dd7070SpatrickkDefaultHost = '127.0.0.1' 27*e5dd7070SpatrickkDefaultPort = 8181 28*e5dd7070SpatrickkMaxPortsToTry = 100 29*e5dd7070Spatrick 30*e5dd7070Spatrick### 31*e5dd7070Spatrick 32*e5dd7070Spatrick 33*e5dd7070Spatrickdef url_is_up(url): 34*e5dd7070Spatrick try: 35*e5dd7070Spatrick o = urlopen(url) 36*e5dd7070Spatrick except IOError: 37*e5dd7070Spatrick return False 38*e5dd7070Spatrick o.close() 39*e5dd7070Spatrick return True 40*e5dd7070Spatrick 41*e5dd7070Spatrick 42*e5dd7070Spatrickdef start_browser(port, options): 43*e5dd7070Spatrick import webbrowser 44*e5dd7070Spatrick 45*e5dd7070Spatrick url = 'http://%s:%d' % (options.host, port) 46*e5dd7070Spatrick 47*e5dd7070Spatrick # Wait for server to start... 48*e5dd7070Spatrick if options.debug: 49*e5dd7070Spatrick sys.stderr.write('%s: Waiting for server.' % sys.argv[0]) 50*e5dd7070Spatrick sys.stderr.flush() 51*e5dd7070Spatrick for i in range(kMaxSleeps): 52*e5dd7070Spatrick if url_is_up(url): 53*e5dd7070Spatrick break 54*e5dd7070Spatrick if options.debug: 55*e5dd7070Spatrick sys.stderr.write('.') 56*e5dd7070Spatrick sys.stderr.flush() 57*e5dd7070Spatrick time.sleep(kSleepTimeout) 58*e5dd7070Spatrick else: 59*e5dd7070Spatrick print('WARNING: Unable to detect that server started.', file=sys.stderr) 60*e5dd7070Spatrick 61*e5dd7070Spatrick if options.debug: 62*e5dd7070Spatrick print('%s: Starting webbrowser...' % sys.argv[0], file=sys.stderr) 63*e5dd7070Spatrick webbrowser.open(url) 64*e5dd7070Spatrick 65*e5dd7070Spatrick 66*e5dd7070Spatrickdef run(port, options, root): 67*e5dd7070Spatrick # Prefer to look relative to the installed binary 68*e5dd7070Spatrick share = os.path.dirname(__file__) + "/../share/scan-view" 69*e5dd7070Spatrick if not os.path.isdir(share): 70*e5dd7070Spatrick # Otherwise look relative to the source 71*e5dd7070Spatrick share = os.path.dirname(__file__) + "/../../scan-view/share" 72*e5dd7070Spatrick sys.path.append(share) 73*e5dd7070Spatrick 74*e5dd7070Spatrick import ScanView 75*e5dd7070Spatrick try: 76*e5dd7070Spatrick print('Starting scan-view at: http://%s:%d' % (options.host, 77*e5dd7070Spatrick port)) 78*e5dd7070Spatrick print(' Use Ctrl-C to exit.') 79*e5dd7070Spatrick httpd = ScanView.create_server((options.host, port), 80*e5dd7070Spatrick options, root) 81*e5dd7070Spatrick httpd.serve_forever() 82*e5dd7070Spatrick except KeyboardInterrupt: 83*e5dd7070Spatrick pass 84*e5dd7070Spatrick 85*e5dd7070Spatrick 86*e5dd7070Spatrickdef port_is_open(port): 87*e5dd7070Spatrick try: 88*e5dd7070Spatrick import socketserver 89*e5dd7070Spatrick except ImportError: 90*e5dd7070Spatrick import SocketServer as socketserver 91*e5dd7070Spatrick try: 92*e5dd7070Spatrick t = socketserver.TCPServer((kDefaultHost, port), None) 93*e5dd7070Spatrick except: 94*e5dd7070Spatrick return False 95*e5dd7070Spatrick t.server_close() 96*e5dd7070Spatrick return True 97*e5dd7070Spatrick 98*e5dd7070Spatrick 99*e5dd7070Spatrickdef main(): 100*e5dd7070Spatrick import argparse 101*e5dd7070Spatrick parser = argparse.ArgumentParser(description="The clang static analyzer " 102*e5dd7070Spatrick "results viewer.") 103*e5dd7070Spatrick parser.add_argument("root", metavar="<results directory>", type=str) 104*e5dd7070Spatrick parser.add_argument( 105*e5dd7070Spatrick '--host', dest="host", default=kDefaultHost, type=str, 106*e5dd7070Spatrick help="Host interface to listen on. (default=%s)" % kDefaultHost) 107*e5dd7070Spatrick parser.add_argument('--port', dest="port", default=None, type=int, 108*e5dd7070Spatrick help="Port to listen on. (default=%s)" % kDefaultPort) 109*e5dd7070Spatrick parser.add_argument("--debug", dest="debug", default=0, 110*e5dd7070Spatrick action="count", 111*e5dd7070Spatrick help="Print additional debugging information.") 112*e5dd7070Spatrick parser.add_argument("--auto-reload", dest="autoReload", default=False, 113*e5dd7070Spatrick action="store_true", 114*e5dd7070Spatrick help="Automatically update module for each request.") 115*e5dd7070Spatrick parser.add_argument("--no-browser", dest="startBrowser", default=True, 116*e5dd7070Spatrick action="store_false", 117*e5dd7070Spatrick help="Don't open a webbrowser on startup.") 118*e5dd7070Spatrick parser.add_argument("--allow-all-hosts", dest="onlyServeLocal", 119*e5dd7070Spatrick default=True, action="store_false", 120*e5dd7070Spatrick help='Allow connections from any host (access ' 121*e5dd7070Spatrick 'restricted to "127.0.0.1" by default)') 122*e5dd7070Spatrick args = parser.parse_args() 123*e5dd7070Spatrick 124*e5dd7070Spatrick # Make sure this directory is in a reasonable state to view. 125*e5dd7070Spatrick if not posixpath.exists(posixpath.join(args.root, 'index.html')): 126*e5dd7070Spatrick parser.error('Invalid directory, analysis results not found!') 127*e5dd7070Spatrick 128*e5dd7070Spatrick # Find an open port. We aren't particularly worried about race 129*e5dd7070Spatrick # conditions here. Note that if the user specified a port we only 130*e5dd7070Spatrick # use that one. 131*e5dd7070Spatrick if args.port is not None: 132*e5dd7070Spatrick port = args.port 133*e5dd7070Spatrick else: 134*e5dd7070Spatrick for i in range(kMaxPortsToTry): 135*e5dd7070Spatrick if port_is_open(kDefaultPort + i): 136*e5dd7070Spatrick port = kDefaultPort + i 137*e5dd7070Spatrick break 138*e5dd7070Spatrick else: 139*e5dd7070Spatrick parser.error('Unable to find usable port in [%d,%d)' % 140*e5dd7070Spatrick (kDefaultPort, kDefaultPort+kMaxPortsToTry)) 141*e5dd7070Spatrick 142*e5dd7070Spatrick # Kick off thread to wait for server and start web browser, if 143*e5dd7070Spatrick # requested. 144*e5dd7070Spatrick if args.startBrowser: 145*e5dd7070Spatrick threading.Thread(target=start_browser, args=(port, args)).start() 146*e5dd7070Spatrick 147*e5dd7070Spatrick run(port, args, args.root) 148*e5dd7070Spatrick 149*e5dd7070Spatrickif __name__ == '__main__': 150*e5dd7070Spatrick main() 151