public Site findSiteByLTIContextId(String externalOaeId) throws Exception {
    Map propertyCriteria = new HashMap();

    // Replace search property
    propertyCriteria.put(LTI_CONTEXT_ID, externalOaeId);

    List list =
        SiteService.getSites(
            org.sakaiproject.site.api.SiteService.SelectionType.ANY,
            null,
            null,
            propertyCriteria,
            org.sakaiproject.site.api.SiteService.SortType.NONE,
            null);

    if (list != null && list.size() > 0) {
      for (Iterator i = list.iterator(); i.hasNext(); ) {
        Site site = (Site) i.next();
        if (site.getProperties() != null) {
          String loadedExternalSiteId = (String) site.getProperties().get(LTI_CONTEXT_ID);
          if (loadedExternalSiteId != null && loadedExternalSiteId.equals(externalOaeId)) {
            // deeply load site, otherwise groups won't be loaded
            M_log.debug("found site: " + site.getId() + " with lti_context_id:" + externalOaeId);
            return SiteService.getSite(site.getId());
          }
        }
      }
    }

    return null;
  }
 protected void invokeProcessors(
     Map payload,
     boolean trustedConsumer,
     ProcessingState processingState,
     User user,
     Site site,
     String toolPlacementId)
     throws LTIException {
   if (!bltiProcessors.isEmpty()) {
     for (BLTIProcessor processor : bltiProcessors) {
       switch (processingState) {
         case beforeValidation:
           processor.beforeValidation(payload, trustedConsumer);
           break;
         case afterValidation:
           processor.afterValidation(payload, trustedConsumer);
           break;
         case afterUserCreation:
           processor.afterUserCreation(payload, user);
           break;
         case afterLogin:
           processor.afterLogin(payload, trustedConsumer, user);
           break;
         case afterSiteCreation:
           processor.afterSiteCreation(payload, trustedConsumer, user, site);
           break;
         case afterSiteMembership:
           processor.afterSiteMembership(payload, trustedConsumer, user, site);
           break;
         case beforeLaunch:
           processor.beforeLaunch(payload, trustedConsumer, user, site, toolPlacementId);
           break;
         default:
           M_log.error("unknown processing state of " + processingState);
       }
     }
   }
 }
  protected void validate(Map payload, boolean isTrustedConsumer) throws LTIException {
    // check parameters
    String lti_message_type = (String) payload.get(BasicLTIConstants.LTI_MESSAGE_TYPE);
    String lti_version = (String) payload.get(BasicLTIConstants.LTI_VERSION);
    String oauth_consumer_key = (String) payload.get("oauth_consumer_key");
    String resource_link_id = (String) payload.get(BasicLTIConstants.RESOURCE_LINK_ID);
    String user_id = (String) payload.get(BasicLTIConstants.USER_ID);
    String context_id = (String) payload.get(BasicLTIConstants.CONTEXT_ID);

    boolean launch = true;
    if (BasicLTIUtil.equals(lti_message_type, "basic-lti-launch-request")) {
      launch = true;
    } else if (BasicLTIUtil.equals(lti_message_type, "ContentItemSelectionRequest")) {
      launch = false;
    } else {
      throw new LTIException("launch.invalid", "lti_message_type=" + lti_message_type, null);
    }

    if (!BasicLTIUtil.equals(lti_version, "LTI-1p0")) {
      throw new LTIException("launch.invalid", "lti_version=" + lti_version, null);
    }

    if (BasicLTIUtil.isBlank(oauth_consumer_key)) {
      throw new LTIException("launch.missing", "oauth_consumer_key", null);
    }

    if (launch && BasicLTIUtil.isBlank(resource_link_id)) {
      throw new LTIException("launch.missing", "resource_link_id", null);
    }

    if (BasicLTIUtil.isBlank(user_id)) {
      throw new LTIException("launch.missing", "user_id", null);
    }
    if (M_log.isDebugEnabled()) {
      M_log.debug("user_id=" + user_id);
    }

    // check tool_id
    String tool_id = (String) payload.get("tool_id");
    if (tool_id == null) {
      throw new LTIException("launch.tool_id.required", null, null);
    }

    // Trim off the leading slash and any trailing space
    tool_id = tool_id.substring(1).trim();
    if (M_log.isDebugEnabled()) {
      M_log.debug("tool_id=" + tool_id);
    }
    // store modified tool_id back in payload
    payload.put("tool_id", tool_id);
    final String allowedToolsConfig =
        ServerConfigurationService.getString("basiclti.provider.allowedtools", "");

    final String[] allowedTools = allowedToolsConfig.split(":");
    final List<String> allowedToolsList = Arrays.asList(allowedTools);

    if (launch && allowedTools != null && !allowedToolsList.contains(tool_id)) {
      throw new LTIException("launch.tool.notallowed", tool_id, null);
    }
    final Tool toolCheck = ToolManager.getTool(tool_id);
    if (launch && toolCheck == null) {
      throw new LTIException("launch.tool.notfound", tool_id, null);
    }

    // Check for the ext_sakai_provider_eid param. If set, this will contain the eid that we are to
    // use
    // in place of using the user_id parameter
    // WE still need that parameter though, so translate it from the given eid.
    boolean useProvidedEid = false;
    String ext_sakai_provider_eid = (String) payload.get(BasicLTIConstants.EXT_SAKAI_PROVIDER_EID);
    if (BasicLTIUtil.isNotBlank(ext_sakai_provider_eid)) {
      useProvidedEid = true;
      try {
        user_id = UserDirectoryService.getUserId(ext_sakai_provider_eid);
      } catch (Exception e) {
        M_log.error(e.getLocalizedMessage(), e);
        throw new LTIException(
            "launch.provided.eid.invalid", "ext_sakai_provider_eid=" + ext_sakai_provider_eid, e);
      }
    }

    if (M_log.isDebugEnabled()) {
      M_log.debug("ext_sakai_provider_eid=" + ext_sakai_provider_eid);
    }

    // Contextualize the context_id with the OAuth consumer key
    // Also use the resource_link_id for the context_id if we did not get a context_id
    // BLTI-31: if trusted, context_id is required and use the param without modification
    if (BasicLTIUtil.isBlank(context_id)) {
      if (isTrustedConsumer) {
        throw new LTIException("launch.missing", context_id, null);
      } else {
        context_id = "res:" + resource_link_id;
        payload.put(BasicLTIConstants.CONTEXT_ID, context_id);
      }
    }

    // Check if context_id is simply a ~. If so, get the id of that user's My Workspace site
    // and use that to construct the full context_id
    if (BasicLTIUtil.equals(context_id, "~")) {
      if (useProvidedEid) {
        String userSiteId = null;
        try {
          userSiteId = SiteService.getUserSiteId(user_id);
        } catch (Exception e) {
          M_log.warn("Failed to get My Workspace site for user_id:" + user_id);
          M_log.error(e.getLocalizedMessage(), e);
          throw new LTIException("launch.user.site.unknown", "user_id=" + user_id, e);
        }
        context_id = userSiteId;
        payload.put(BasicLTIConstants.CONTEXT_ID, context_id);
      }
    }

    if (M_log.isDebugEnabled()) {
      M_log.debug("context_id=" + context_id);
    }

    // Lookup the secret
    final String configPrefix = "basiclti.provider." + oauth_consumer_key + ".";
    final String oauth_secret = ServerConfigurationService.getString(configPrefix + "secret", null);
    if (oauth_secret == null) {
      throw new LTIException("launch.key.notfound", oauth_consumer_key, null);
    }
    final OAuthMessage oam = (OAuthMessage) payload.get("oauth_message");

    final String forcedURIScheme =
        ServerConfigurationService.getString("basiclti.provider.forcedurischeme", null);

    if (forcedURIScheme != null) {
      try {
        URI testURI = new URI(oam.URL);
        URI newURI = new URI(forcedURIScheme, testURI.getSchemeSpecificPart(), null);
        oam.URL = newURI.toString();
      } catch (URISyntaxException use) {
      }
    }
    final OAuthValidator oav = new SimpleOAuthValidator();
    final OAuthConsumer cons =
        new OAuthConsumer(
            "about:blank#OAuth+CallBack+NotUsed", oauth_consumer_key, oauth_secret, null);

    final OAuthAccessor acc = new OAuthAccessor(cons);

    String base_string = null;
    try {
      base_string = OAuthSignatureMethod.getBaseString(oam);
    } catch (Exception e) {
      M_log.error(e.getLocalizedMessage(), e);
      base_string = null;
    }

    try {
      oav.validateMessage(oam, acc);
    } catch (Exception e) {
      M_log.warn("Provider failed to validate message");
      M_log.warn(e.getLocalizedMessage(), e);
      if (base_string != null) {
        M_log.warn(base_string);
      }
      throw new LTIException("launch.no.validate", context_id, e);
    }

    final Session sess = SessionManager.getCurrentSession();

    if (sess == null) {
      throw new LTIException("launch.no.session", context_id, null);
    }
  }
  private void handleContentItem(
      HttpServletRequest request, HttpServletResponse response, Map payload)
      throws ServletException, IOException {

    String allowedToolsConfig =
        ServerConfigurationService.getString("basiclti.provider.allowedtools", "");
    String[] allowedTools = allowedToolsConfig.split(":");
    List<String> allowedToolsList = Arrays.asList(allowedTools);

    String tool_id = (String) request.getParameter("install");
    if (tool_id == null) {
      ArrayList<Tool> tools = new ArrayList<Tool>();
      for (String toolId : allowedToolsList) {
        Tool theTool = ToolManager.getTool(toolId);
        if (theTool == null) continue;
        tools.add(theTool);
      }
      request.setAttribute("tools", tools);
    } else {
      if (!allowedToolsList.contains(tool_id)) {
        doError(request, response, "launch.tool.notallowed", tool_id, null);
        return;
      }
      final Tool toolCheck = ToolManager.getTool(tool_id);
      if (toolCheck == null) {
        doError(request, response, "launch.tool.notfound", tool_id, null);
        return;
      }

      String content_item_return_url = (String) payload.get("content_item_return_url");
      if (content_item_return_url == null) {
        doError(request, response, "content_item.return_url.notfound", tool_id, null);
        return;
      }

      ContentItemResponse resp = SakaiContentItemUtil.getContentItemResponse(tool_id);
      if (resp == null) {
        doError(request, response, "launch.tool.notfound", tool_id, null);
        return;
      }
      String content_items = resp.prettyPrintLog();

      // Set up the return
      Map<String, String> ltiMap = new HashMap<String, String>();
      Map<String, String> extra = new HashMap<String, String>();
      ltiMap.put(
          BasicLTIConstants.LTI_MESSAGE_TYPE,
          BasicLTIConstants.LTI_MESSAGE_TYPE_CONTENTITEMSELECTION);
      ltiMap.put(BasicLTIConstants.LTI_VERSION, BasicLTIConstants.LTI_VERSION_1);
      ltiMap.put("content_items", content_items);
      String data = (String) payload.get("data");
      if (data != null) ltiMap.put("data", data);
      M_log.debug("ltiMap=" + ltiMap);

      boolean dodebug = M_log.isDebugEnabled();
      boolean autosubmit = false;
      String launchtext = rb.getString("content_item.install.button");
      String back_to_store = rb.getString("content_item.back.to.store");
      extra.put(
          "button_html",
          "<input type=\"submit\" value=\""
              + back_to_store
              + "\"onclick=\"location.href='content.item'; return false;\">");
      String launch_html =
          BasicLTIUtil.postLaunchHTML(
              ltiMap, content_item_return_url, launchtext, autosubmit, dodebug, extra);

      request.setAttribute("back_to_store", rb.getString("content_item.back.to.store"));
      request.setAttribute("install", tool_id);
      request.setAttribute("launch_html", launch_html);
      request.setAttribute("tool", toolCheck);
    }

    // Forward to the JSP
    ServletContext sc = this.getServletContext();
    RequestDispatcher rd = sc.getRequestDispatcher("/contentitem.jsp");
    try {
      rd.forward(request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }