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. &nbsp; '
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        ' &nbsp; <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