1import os 2import time 3 4from WebKit.URLParser import ServletFactoryManager 5from WebUtils.Funcs import htmlEncode 6from AdminSecurity import AdminSecurity 7 8 9class ServletCache(AdminSecurity): 10 """Display servlet cache. 11 12 This servlet displays, in a readable form, the internal data 13 structure of the cache of all servlet factories. 14 15 This can be useful for debugging WebKit problems and the 16 information is interesting in general. 17 """ 18 19 def title(self): 20 return 'Servlet Cache' 21 22 def writeContent(self): 23 wr = self.writeln 24 factories = [factory for factory in ServletFactoryManager._factories 25 if factory._classCache] 26 if not factories: 27 wr('<h4>No caching servlet factories found.</h4>') 28 wr('<p>Caching can be activated by setting' 29 ' <code>CacheServletClasses = True</code>.</p>') 30 return 31 if len(factories) > 1: 32 factories.sort() 33 wr('<h3>Servlet Factories:</h3>') 34 wr('<table>') 35 for factory in factories: 36 wr('<tr><td><a href="#%s">%s</a></td></tr>' 37 % ((factory.name(),)*2)) 38 wr('</table>') 39 req = self.request() 40 wr('<form action="ServletCache" method="post">') 41 for factory in factories: 42 name = factory.name() 43 wr('<a id="%s"></a><h4>%s</h4>' % ((name,)*2)) 44 if req.hasField('flush_' + name): 45 factory.flushCache() 46 wr('<p style="color:green">' 47 'The servlet cache has been flushed. ' 48 '<input type="submit" name="reload" value="Reload"></p>') 49 continue 50 wr(htCache(factory)) 51 wr('</form>') 52 53def htCache(factory): 54 """Output the cache of a servlet factory.""" 55 html = [] 56 wr = html.append 57 cache = factory._classCache 58 keys = sorted(cache) 59 wr('<p>Uniqueness: %s</p>' % factory.uniqueness()) 60 wr('<p>Extensions: %s</p>' % ', '.join(map(repr, factory.extensions()))) 61 wr('<p>Unique paths in the servlet cache: <strong>%d</strong>' 62 ' <input type="submit" name="flush_%s" value="Flush"></p>' 63 % (len(keys), factory.name())) 64 wr('<p>Click any link to jump to the details for that path.</p>') 65 wr('<h5>Filenames:</h5>') 66 wr('<table class="NiceTable">') 67 wr('<tr><th>File</th><th>Directory</th></tr>') 68 paths = [] 69 for key in keys: 70 head, tail = os.path.split(key) 71 path = dict(dir=head, base=tail, full=key) 72 paths.append(path) 73 paths.sort(key=lambda p: (p['base'].lower(), p['dir'].lower())) 74 # At this point, paths is a list where each element is a dictionary 75 # with directory name, base name, full path name sorted first by 76 # base name and second by dir name. 77 for path in paths: 78 wr('<tr><td><a href="#id%s">%s</a></td><td>%s</td></tr>' 79 % (id(path['full']), path['base'], path['dir'])) 80 wr('</table>') 81 wr('<h5>Full paths:</h5>') 82 wr('<table class="NiceTable">') 83 wr('<tr><th>Servlet path</th></tr>') 84 for key in keys: 85 wr('<tr><td><a href="#%s">%s</a></td></tr>' % (id(key), key)) 86 wr('</table>') 87 wr('<h5>Details:</h5>') 88 wr('<table class="NiceTable">') 89 for path in paths: 90 wr('<tr class="NoTable"><td colspan="2">' 91 '<a id="id%s"></a><strong>%s</strong> - %s</td></tr>' 92 % (id(path['full']), path['base'], path['dir'])) 93 record = cache[path['full']].copy() 94 record['path'] = path['full'] 95 if path['full'] in factory._threadsafeServletCache: 96 record['instances'] = 'one servlet instance (threadsafe)' 97 else: 98 record['instances'] = ('free reusable servlets: %d' 99 % len(factory._servletPool)) 100 wr(htRecord(record)) 101 wr('</table>') 102 return '\n'.join(html) 103 104def htRecord(record): 105 html = [] 106 wr = html.append 107 for key in sorted(record): 108 htKey = htmlEncode(key) 109 # determine the HTML for the value 110 value = record[key] 111 htValue = None 112 # check for special cases where we want a custom display 113 if hasattr(value, '__name__'): 114 htValue = value.__name__ 115 if key == 'mtime': 116 htValue = '%s (%s)' % (time.asctime(time.localtime(value)), value) 117 # the general case: 118 if not htValue: 119 htValue = htmlEncode(str(value)) 120 wr('<tr><th>%s</th><td>%s</td></tr>' % (htKey, htValue)) 121 return '\n'.join(html) 122