public override void service(ServletRequest request, ServletResponse response)

        {
            QuercusHttpServletRequest req
                = new QuercusHttpServletRequestImpl((HttpServletRequest)request);
            HttpServletResponse res = (HttpServletResponse)response;

            string uri = QuercusRequestAdapter.getPageURI(req);

            CacheEntry entry = _cache.get(uri);

            if (entry == null)
            {
                string path    = getPath(req);
                string relPath = path.getUserPath();

                string mimeType = _context.getMimeType(uri);

                entry = new CacheEntry(path, relPath, mimeType);
                _cache.put(uri, entry);
            }
            else if (entry.isModified())
            {
                entry = new CacheEntry(entry.getPath(),
                                       entry.getRelPath(),
                                       entry.getMimeType());

                _cache.put(uri, entry);
            }

            string ifMatch = req.getHeader("If-None-Match");
            string etag    = entry.getEtag();

            if (ifMatch != null && ifMatch.equals(etag))
            {
                res.addHeader("ETag", etag);
                res.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                return;
            }

            string lastModified = entry.getLastModifiedString();

            if (ifMatch == null)
            {
                string ifModified = req.getHeader("If-Modified-Since");

                bool isModified = true;

                if (ifModified == null)
                {
                }
                else if (ifModified.equals(lastModified))
                {
                    isModified = false;
                }
                else
                {
                    long ifModifiedTime;

                    QDate date = QDate.allocateLocalDate();

                    try {
                        ifModifiedTime = date.parseDate(ifModified);
                    } catch (Exception e) {
                        log.log(Level.FINER, e.ToString(), e);

                        ifModifiedTime = 0;
                    }

                    QDate.freeLocalDate(date);

                    isModified = ifModifiedTime == 0 ||
                                 ifModifiedTime != entry.getLastModified();
                }

                if (!isModified)
                {
                    if (etag != null)
                    {
                        res.addHeader("ETag", etag);
                    }

                    res.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                    return;
                }
            }

            res.addHeader("ETag", etag);
            res.addHeader("Last-Modified", lastModified);

            string mime = entry.getMimeType();

            if (mime != null)
            {
                res.setContentType(mime);
            }

            res.setContentLength((int)entry.getLength());

            string method = req.getMethod();

            if (method.equalsIgnoreCase("HEAD"))
            {
                return;
            }

            string path = entry.getPath();

            if (path.isDirectory())
            {
                res.sendError(HttpServletResponse.SC_NOT_FOUND);

                return;
            }
            else if (!path.canRead())
            {
                res.sendError(HttpServletResponse.SC_NOT_FOUND);

                return;
            }

            OutputStream os = response.getOutputStream();

            path.writeToStream(os);
        }