// cache the template...
  protected Transformer getTransformer(Presentation presentation, Map request)
      throws PersistenceException {
    Id renderer = presentation.getTemplate().getRenderer();
    TransformerWrapper wrapper = (TransformerWrapper) presentationTemplateCache.get(renderer);

    if (wrapper == null) {
      wrapper = new TransformerWrapper();
      wrapper.modified = 0;
    }

    Node xsl = getPresentationManager().getNode(renderer);

    if (xsl.getTechnicalMetadata().getLastModified().getTime() > wrapper.modified) {
      try {
        wrapper.transformer =
            TransformerFactory.newInstance().newTransformer(new StreamSource(xsl.getInputStream()));
        wrapper.modified = xsl.getTechnicalMetadata().getLastModified().getTime();
      } catch (TransformerConfigurationException e) {
        throw new OspException(e);
      }
    }

    wrapper.transformer.clearParameters();

    // send request params in as transform params
    for (Iterator i = request.keySet().iterator(); i.hasNext(); ) {
      String paramName = (String) i.next();
      wrapper.transformer.setParameter(paramName, request.get(paramName));
    }

    presentationTemplateCache.put(renderer, wrapper);

    return wrapper.transformer;
  }
  public ModelAndView handleRequest(
      Object requestModel, Map request, Map session, Map application, Errors errors) {
    Presentation pres = (Presentation) requestModel;

    if (pres.getSecretExportKey() == null) {
      if (!pres.getIsPublic()) {
        if (getAuthManager().getAgent().isInRole(Agent.ROLE_ANONYMOUS)) {
          try {
            Site site = SiteService.getSite(pres.getSiteId());
            ToolConfiguration toolConfig =
                site.getToolForCommonId(PresentationFunctionConstants.PRES_TOOL_ID);
            String placement = toolConfig.getId();
            ToolSession ts = SessionManager.getCurrentSession().getToolSession(placement);
            SessionManager.setCurrentToolSession(ts);

            SessionManager.getCurrentSession()
                .setAttribute(Tool.HELPER_DONE_URL, pres.getExternalUri());

            Map model = new Hashtable();
            model.put("sakai.tool.placement.id", placement);
            return new ModelAndView("authnRedirect", model);

          } catch (IdUnusedException e) {
            logger.error("", e);
          }
        } else {

          getAuthzManager()
              .checkPermission(PresentationFunctionConstants.VIEW_PRESENTATION, pres.getId());
        }
      }

      if (pres.isExpired()
          && !pres.getOwner().getId().equals(getAuthManager().getAgent().getId())) {
        return new ModelAndView("expired");
      }
    }

    if (!pres.isPreview()) {
      logViewedPresentation(pres);
    }

    Hashtable model = new Hashtable();

    try {
      model.put("presentation", pres);
      Document doc = null;

      if (pres.getPresentationType().equals(Presentation.TEMPLATE_TYPE))
        doc = getPresentationManager().createDocument(pres);
      else {
        String page = (String) request.get("page");
        if (pres.isPreview()) {
          doc = getPresentationManager().getPresentationPreviewLayoutAsXml(pres, page);
        } else {
          doc = getPresentationManager().getPresentationLayoutAsXml(pres, page);
        }
      }
      Site site = SiteService.getSite(pres.getSiteId());
      getAuthzManager().pushAuthzGroups(site.getId());
      ToolConfiguration toolConfig =
          site.getToolForCommonId(PresentationFunctionConstants.PRES_TOOL_ID);
      String placement = toolConfig.getId();
      model.put("placementId", placement);
      if (doc != null) model.put("document", doc);
      else return new ModelAndView("notFound", model);
      model.put("renderer", getTransformer(pres, request));
      model.put("uriResolver", getUriResolver());

      if (!getAuthManager().getAgent().isInRole(Agent.ROLE_ANONYMOUS)) {
        model.put("currentAgent", getAuthManager().getAgent());
      }

      if (!pres.isPreview()) {
        model.put(
            "comments",
            getPresentationManager()
                .getPresentationComments(pres.getId(), getAuthManager().getAgent()));

        boolean allowComments =
            getAuthzManager()
                .isAuthorized(PresentationFunctionConstants.COMMENT_PRESENTATION, pres.getId());
        model.put("allowComments", allowComments);
      } else {
        model.put("allowComments", pres.isAllowComments());
      }

      if (request.get(BindException.ERROR_KEY_PREFIX + "newComment") == null) {
        request.put(
            BindException.ERROR_KEY_PREFIX + "newComment",
            new BindException(new PresentationComment(), "newComment"));
      }

    } catch (PersistenceException e) {
      logger.error("", e);
      throw new OspException(e);
    } catch (IdUnusedException e) {
      logger.error("", e);
    }

    boolean headers = pres.getTemplate().isIncludeHeaderAndFooter();
    String viewName = "withoutHeader";

    if (headers) {
      if (ToolManager.getCurrentPlacement() == null) {
        viewName = "withHeaderStandalone";
      } else {
        viewName = "withHeader";
      }
    }
    return new ModelAndView(viewName, model);
  }