  public boolean service(WebloungeRequest request, WebloungeResponse response) {
    Site site = request.getSite();
    String path = request.getRequestURI();
    String feedType = null;
    if (!path.startsWith(URI_PREFIX) || !(path.length() > URI_PREFIX.length()))
      return false;
    String requestMethod = request.getMethod();
    if (!"GET".equals(requestMethod)) {
      logger.debug("Feed request handler does not support {} requests", requestMethod);
      return false;
    }
    ContentRepository contentRepository = site.getContentRepository();
    if (contentRepository == null) {
      logger.warn("No content repository found for site '{}'", site);
      return false;
    }
    String feedURI = path.substring(URI_PREFIX.length());
    String[] feedURIParts = feedURI.split("/");
    if (feedURIParts.length == 0) {
      logger.debug("Feed request {} does not include feed type", path);
      return false;
    } else if (feedURIParts.length == 1) {
      logger.debug("Feed request {} does not include feed version", path);
      return false;
    }
    String[] subjectParameter = request.getParameterValues(PARAM_SUBJECT);
    List<String> subjects = new ArrayList<String>();
    if (subjectParameter != null) {
      for (String parameter : subjectParameter) {
        for (String subject : parameter.split(",")) {
          if (StringUtils.isNotBlank(subject))
            subjects.add(StringUtils.trim(subject));
        }
      }
    }
    int limit = DEFAULT_LIMIT;
    String limitParameter = StringUtils.trimToNull(request.getParameter(PARAM_LIMIT));
    if (limitParameter != null) {
      try {
        limit = Integer.parseInt(limitParameter);
      } catch (Throwable t) {
        logger.debug("Non parseable number {} specified as limit", limitParameter);
        limit = DEFAULT_LIMIT;
      }
    }
    Language language = request.getLanguage();
    feedType = feedURIParts[0].toLowerCase() + "_" + feedURIParts[1];
    SyndFeed feed = new SyndFeedImpl();
    feed.setFeedType(feedType);
    feed.setLink(request.getRequestURL().toString());
    feed.setTitle(site.getName());
    feed.setLanguage(language.getDescription());
    try {
      SearchQuery query = new SearchQueryImpl(site);
      query.withType(Page.TYPE);
      query.withLimit(limit);
      query.sortByModificationDate(Order.Descending);
      for (String subject : subjects) {
        query.withSubject(subject);
      }
      SearchResult result = contentRepository.find(query);
      List<SyndEntry> entries = new ArrayList<SyndEntry>();
      for (SearchResultItem item : result.getItems()) {
        if (limit == 0)
          break;
        SearchResultPageItem pageItem = (SearchResultPageItem)item;
        Page page = pageItem.getPage();
        page.switchTo(language);
        SyndEntry entry = new SyndEntryImpl();
        entry.setPublishedDate(page.getPublishFrom());
        entry.setLink(item.getUrl().getLink());
        entry.setAuthor(page.getCreator().getName());
        entry.setCategories(Arrays.asList(page.getSubjects()));
        entry.setTitle(item.getTitle());
        entries.add(entry);
        limit--;
      }
      feed.setEntries(entries);
    } catch (ContentRepositoryException e) {
      logger.error("Error loading articles for feeds from {}: {}", contentRepository, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    }
    if ("atom".equalsIgnoreCase("atom"))
      response.setContentType("application/atom+xml");
    else if ("rss".equalsIgnoreCase(feedType))
      response.setContentType("application/rss+xml");
    response.setCharacterEncoding(feed.getEncoding());
    try {
      SyndFeedOutput output = new SyndFeedOutput();
      Writer responseWriter = new OutputStreamWriter(response.getOutputStream());
      output.output(feed, responseWriter);
      response.getOutputStream().flush();
      return true;
    } catch (FeedException e) {
      logger.error("Error creating {} feed: {}", feedType, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    } catch (IOException e) {
      logger.error("Error sending {} feed to the client: {}", feedType, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    }
  }

  public boolean service(WebloungeRequest request, WebloungeResponse response) {
    Site site = request.getSite();
    String path = request.getRequestURI();
    String feedType = null;
    if (!path.startsWith(URI_PREFIX) || !(path.length() > URI_PREFIX.length()))
      return false;
    String requestMethod = request.getMethod();
    if (!"GET".equals(requestMethod)) {
      logger.debug("Feed request handler does not support {} requests", requestMethod);
      return false;
    }
    ContentRepository contentRepository = site.getContentRepository();
    if (contentRepository == null) {
      logger.warn("No content repository found for site '{}'", site);
      return false;
    }
    String feedURI = path.substring(URI_PREFIX.length());
    String[] feedURIParts = feedURI.split("/");
    if (feedURIParts.length == 0) {
      logger.debug("Feed request {} does not include feed type", path);
      return false;
    } else if (feedURIParts.length == 1) {
      logger.debug("Feed request {} does not include feed version", path);
      return false;
    }
    String[] subjectParameter = request.getParameterValues(PARAM_SUBJECT);
    List<String> subjects = new ArrayList<String>();
    if (subjectParameter != null) {
      for (String parameter : subjectParameter) {
        for (String subject : parameter.split(",")) {
          if (StringUtils.isNotBlank(subject))
            subjects.add(StringUtils.trim(subject));
        }
      }
    }
    int limit = DEFAULT_LIMIT;
    String limitParameter = StringUtils.trimToNull(request.getParameter(PARAM_LIMIT));
    if (limitParameter != null) {
      try {
        limit = Integer.parseInt(limitParameter);
      } catch (Throwable t) {
        logger.debug("Non parseable number {} specified as limit", limitParameter);
        limit = DEFAULT_LIMIT;
      }
    }
    Language language = request.getLanguage();
    feedType = feedURIParts[0].toLowerCase() + "_" + feedURIParts[1];
    SyndFeed feed = new SyndFeedImpl();
    feed.setFeedType(feedType);
    feed.setLink(request.getRequestURL().toString());
    feed.setTitle(site.getName());
    feed.setLanguage(language.getDescription());
    try {
      SearchQuery query = new SearchQueryImpl(site);
      query.withType(Page.TYPE);
      query.withLimit(limit);
      query.sortByModificationDate(Order.Descending);
      for (String subject : subjects) {
        query.withSubject(subject);
      }
      SearchResult result = contentRepository.find(query);
      List<SyndEntry> entries = new ArrayList<SyndEntry>();
      for (SearchResultItem item : result.getItems()) {
        if (limit == 0)
          break;
        SearchResultPageItem pageItem = (SearchResultPageItem)item;
        Page page = pageItem.getPage();
        page.switchTo(language);
        SyndEntry entry = new SyndEntryImpl();
        entry.setPublishedDate(page.getPublishFrom());
        entry.setLink(item.getUrl().getLink());
        entry.setAuthor(page.getCreator().getName());
        entry.setCategories(Arrays.asList(page.getSubjects()));
        entry.setTitle(page.getTitle());
        entries.add(entry);
        limit--;
      }
      feed.setEntries(entries);
    } catch (ContentRepositoryException e) {
      logger.error("Error loading articles for feeds from {}: {}", contentRepository, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    }
    if ("atom".equalsIgnoreCase("atom"))
      response.setContentType("application/atom+xml");
    else if ("rss".equalsIgnoreCase(feedType))
      response.setContentType("application/rss+xml");
    response.setCharacterEncoding(feed.getEncoding());
    try {
      SyndFeedOutput output = new SyndFeedOutput();
      Writer responseWriter = new OutputStreamWriter(response.getOutputStream());
      output.output(feed, responseWriter);
      response.getOutputStream().flush();
      return true;
    } catch (FeedException e) {
      logger.error("Error creating {} feed: {}", feedType, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    } catch (IOException e) {
      logger.error("Error sending {} feed to the client: {}", feedType, e.getMessage());
      DispatchUtils.sendInternalError(request, response);
      return true;
    }
  }
