Home | History | Annotate | Download | only in scan-view
      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