/**
  * Does a gradebook exist?
  *
  * @param siteId the site id
  * @return true if the given gradebook exists
  */
 public boolean isGradebookExist(String siteId) {
   Site currentSite = getCurrentSite(siteId);
   if (currentSite == null) {
     return false;
   }
   SitePage page = null;
   String toolId = null;
   try {
     // get page
     List pageList = currentSite.getPages();
     for (int i = 0; i < pageList.size(); i++) {
       page = (SitePage) pageList.get(i);
       List pageToolList = page.getTools();
       try {
         toolId = ((ToolConfiguration) pageToolList.get(0)).getTool().getId();
       } catch (Exception ee) {
         log.warn(
             siteId
                 + " contains a page ("
                 + page.getTitle()
                 + ") without a valid tool registration");
       }
       if (toolId != null && toolId.equalsIgnoreCase("sakai.gradebook.tool")) {
         return true;
       } else if (toolId != null && toolId.equalsIgnoreCase("sakai.gradebook.gwt.rpc")) {
         return true;
       }
     }
   } catch (Exception e) {
     log.warn(e.getMessage());
   }
   return false;
 }
  /**
   * Retrieve the list of pages in this site, checking to see if the user has permission to see the
   * page - by checking the permissions of tools on the page.
   *
   * @param site
   * @return
   */
  public List getPermittedPagesInOrder(Site site) {
    // Get all of the pages
    List pages = site.getOrderedPages();
    boolean siteUpdate = SecurityService.unlock("site.upd", site.getReference());

    List newPages = new ArrayList();

    for (Iterator i = pages.iterator(); i.hasNext(); ) {
      // check if current user has permission to see page
      SitePage p = (SitePage) i.next();
      List pTools = p.getTools();
      Iterator iPt = pTools.iterator();

      boolean allowPage = false;
      while (iPt.hasNext()) {
        ToolConfiguration placement = (ToolConfiguration) iPt.next();

        boolean thisTool = allowTool(site, placement);
        boolean unHidden = siteUpdate || !isHidden(placement);
        if (thisTool && unHidden) allowPage = true;
      }
      if (allowPage) newPages.add(p);
    }

    PageFilter pageFilter = portal.getPageFilter();

    if (pageFilter != null) {
      newPages = pageFilter.filter(newPages, site);
    }
    return newPages;
  }
  /**
   * @param p
   * @return
   */
  private Map createPageProps(SitePage p) {
    Map properties = new HashMap();
    for (Iterator<String> i = p.getProperties().getPropertyNames(); i.hasNext(); ) {
      String propName = i.next();
      properties.put(propName, p.getProperties().get(propName));
    }

    return properties;
  }
 public String lookupPageToAlias(String siteId, SitePage page) {
   // Shortcut if we aren't using page aliases.
   if (!lookForPageAliases) {
     return null;
   }
   String alias = null;
   List<Alias> aliases = AliasService.getAliases(page.getReference());
   if (aliases.size() > 0) {
     if (aliases.size() > 1 && log.isWarnEnabled()) {
       log.warn("More than one alias for: " + siteId + ":" + page.getId());
       // Sort on ID so it is consistent in the alias it uses.
       Collections.sort(aliases, getAliasComparator());
     }
     alias = aliases.get(0).getId();
     alias = parseAlias(alias, siteId);
   }
   return alias;
 }
  public boolean summarizePage(Map m, Site site, SitePage page) {
    List pTools = page.getTools();
    Iterator iPt = pTools.iterator();
    while (iPt.hasNext()) {
      ToolConfiguration placement = (ToolConfiguration) iPt.next();

      if (summarizeTool(m, site, placement.getToolId())) {
        return true;
      }
    }
    return false;
  }
  /**
   * Make sure that we have a proper page selected in the site pageid is generally the last page
   * used in the site. pageId must be in the site and the user must have permission for the page as
   * well.
   *
   * @see org.sakaiproject.portal.api.PortalSiteHelper#lookupSitePage(java.lang.String,
   *     org.sakaiproject.site.api.Site)
   */
  public SitePage lookupSitePage(String pageId, Site site) {
    // Make sure we have some permitted pages
    List pages = getPermittedPagesInOrder(site);
    if (pages.isEmpty()) return null;
    SitePage page = site.getPage(pageId);
    if (page == null) {
      page = lookupAliasToPage(pageId, site);
      if (page == null) {
        page = (SitePage) pages.get(0);
        return page;
      }
    }

    // Make sure that they user has permission for the page.
    // If the page is not in the permitted list go to the first
    // page.
    boolean found = false;
    for (Iterator i = pages.iterator(); i.hasNext(); ) {
      SitePage p = (SitePage) i.next();
      if (p.getId().equals(page.getId())) return page;
    }

    return (SitePage) pages.get(0);
  }
  /**
   * Produce a page and/or a tool list doPage = true is best for the tabs-based portal and for RSS -
   * these think in terms of pages doPage = false is best for the portlet-style - it unrolls all of
   * the tools unless a page is marked as a popup. If the page is a popup - it is left a page and
   * marked as such. restTools = true - generate resetting tool URLs.
   *
   * @see
   *     org.sakaiproject.portal.api.PortalSiteHelper#pageListToMap(javax.servlet.http.HttpServletRequest,
   *     boolean, org.sakaiproject.site.api.Site, org.sakaiproject.site.api.SitePage,
   *     java.lang.String, java.lang.String, boolean, boolean, boolean)
   */
  public Map pageListToMap(
      HttpServletRequest req,
      boolean loggedIn,
      Site site,
      SitePage page,
      String toolContextPath,
      String portalPrefix,
      boolean doPages,
      boolean resetTools,
      boolean includeSummary) {

    Map<String, Object> theMap = new HashMap<String, Object>();

    String pageUrl =
        Web.returnUrl(
            req, "/" + portalPrefix + "/" + Web.escapeUrl(getSiteEffectiveId(site)) + "/page/");
    String toolUrl =
        Web.returnUrl(req, "/" + portalPrefix + "/" + Web.escapeUrl(getSiteEffectiveId(site)));
    if (resetTools) {
      toolUrl = toolUrl + "/tool-reset/";
    } else {
      toolUrl = toolUrl + "/tool/";
    }

    String pagePopupUrl = Web.returnUrl(req, "/page/");
    boolean showHelp = ServerConfigurationService.getBoolean("display.help.menu", true);
    String iconUrl = "";
    try {
      if (site.getIconUrlFull() != null) iconUrl = new URI(site.getIconUrlFull()).toString();
    } catch (URISyntaxException uex) {
      log.debug("Icon URL is invalid: " + site.getIconUrlFull());
    }

    boolean published = site.isPublished();
    String type = site.getType();

    theMap.put("siteId", site.getId());
    theMap.put("pageNavPublished", Boolean.valueOf(published));
    theMap.put("pageNavType", type);
    theMap.put("pageNavIconUrl", iconUrl);
    String htmlInclude = site.getProperties().getProperty(PROP_HTML_INCLUDE);
    if (htmlInclude != null) theMap.put("siteHTMLInclude", htmlInclude);

    // theMap.put("pageNavSitToolsHead",
    // Web.escapeHtml(rb.getString("sit_toolshead")));

    // order the pages based on their tools and the tool order for the
    // site type
    // List pages = site.getOrderedPages();
    List pages = getPermittedPagesInOrder(site);

    List<Map> l = new ArrayList<Map>();

    String addMoreToolsUrl = null;
    for (Iterator i = pages.iterator(); i.hasNext(); ) {

      SitePage p = (SitePage) i.next();
      // check if current user has permission to see page
      // we will draw page button if it have permission to see at least
      // one tool on the page
      List<ToolConfiguration> pTools = p.getTools();
      ToolConfiguration firstTool = null;
      String toolsOnPage = null;

      boolean current = (page != null && p.getId().equals(page.getId()) && !p.isPopUp());
      String alias = lookupPageToAlias(site.getId(), p);
      String pagerefUrl = pageUrl + Web.escapeUrl((alias != null) ? alias : p.getId());

      if (doPages || p.isPopUp()) {
        Map<String, Object> m = new HashMap<String, Object>();
        StringBuffer desc = new StringBuffer();

        boolean hidden = false;
        if (pTools != null && pTools.size() > 0) {
          firstTool = pTools.get(0);
          hidden = true; // Only set the page to hidden when we have tools that might un-hide it.
          Iterator<ToolConfiguration> tools = pTools.iterator();
          // get the tool descriptions for this page, typically only one per page, execpt for the
          // Home page
          int tCount = 0;
          while (tools.hasNext()) {
            ToolConfiguration t = tools.next();
            if (hidden && !isHidden(t)) {
              hidden = false;
            }
            if (tCount > 0) {
              desc.append(" | ");
            }
            if (t.getTool() == null) continue;
            desc.append(t.getTool().getDescription());
            tCount++;
            if ("sakai.siteinfo".equals(t.getToolId())) {
              addMoreToolsUrl =
                  Web.returnUrl(
                      req,
                      "/site/"
                          + Web.escapeUrl(site.getId())
                          + "/page/"
                          + Web.escapeUrl(p.getId())
                          + "?sakai_action=doMenu_edit_site_tools&panel=Shortcut");
            }
          }
          // Won't work with mutliple tools per page
          if (tCount > 1) addMoreToolsUrl = null;
        }

        boolean siteUpdate = SecurityService.unlock("site.upd", site.getReference());
        if (!siteUpdate) addMoreToolsUrl = null;

        if (!ServerConfigurationService.getBoolean("portal.experimental.addmoretools", false))
          addMoreToolsUrl = null;

        m.put("isPage", Boolean.valueOf(true));
        m.put("current", Boolean.valueOf(current));
        m.put("ispopup", Boolean.valueOf(p.isPopUp()));
        m.put("pagePopupUrl", pagePopupUrl);
        m.put("pageTitle", Web.escapeHtml(p.getTitle()));
        m.put("jsPageTitle", Web.escapeJavascript(p.getTitle()));
        m.put("pageId", Web.escapeUrl(p.getId()));
        m.put("jsPageId", Web.escapeJavascript(p.getId()));
        m.put("pageRefUrl", pagerefUrl);

        // TODO: Should have Web.escapeHtmlAttribute()
        String description = desc.toString().replace("\"", "&quot;");
        m.put("description", description);
        m.put("hidden", Boolean.valueOf(hidden));
        // toolsOnPage is always null
        // if (toolsOnPage != null) m.put("toolsOnPage", toolsOnPage);
        if (includeSummary) summarizePage(m, site, p);
        if (firstTool != null) {
          String menuClass = firstTool.getToolId();
          menuClass = "icon-" + menuClass.replace('.', '-');
          m.put("menuClass", menuClass);
          Properties tmp = firstTool.getConfig();
          if (tmp != null) {
            String mc = tmp.getProperty(PROP_MENU_CLASS);
            if (mc != null && mc.length() > 0) m.put("menuClassOverride", mc);
          }
        } else {
          m.put("menuClass", "icon-default-tool");
        }
        m.put("pageProps", createPageProps(p));
        // this is here to allow the tool reorder to work
        m.put("_sitePage", p);
        l.add(m);
        continue;
      }

      // Loop through the tools again and Unroll the tools
      Iterator iPt = pTools.iterator();

      while (iPt.hasNext()) {
        ToolConfiguration placement = (ToolConfiguration) iPt.next();

        Tool tool = placement.getTool();
        if (tool != null) {
          String toolrefUrl = toolUrl + Web.escapeUrl(placement.getId());

          Map<String, Object> m = new HashMap<String, Object>();
          m.put("isPage", Boolean.valueOf(false));
          m.put("toolId", Web.escapeUrl(placement.getId()));
          m.put("jsToolId", Web.escapeJavascript(placement.getId()));
          m.put("toolRegistryId", placement.getToolId());
          m.put("toolTitle", Web.escapeHtml(placement.getTitle()));
          m.put("jsToolTitle", Web.escapeJavascript(placement.getTitle()));
          m.put("toolrefUrl", toolrefUrl);
          String menuClass = placement.getToolId();
          menuClass = "icon-" + menuClass.replace('.', '-');
          m.put("menuClass", menuClass);
          Properties tmp = placement.getConfig();
          if (tmp != null) {
            String mc = tmp.getProperty(PROP_MENU_CLASS);
            if (mc != null && mc.length() > 0) m.put("menuClassOverride", mc);
          }
          // this is here to allow the tool reorder to work if requried.
          m.put("_placement", placement);
          l.add(m);
        }
      }
    }
    PageFilter pageFilter = portal.getPageFilter();
    if (pageFilter != null) {
      l = pageFilter.filterPlacements(l, site);
    }

    if (addMoreToolsUrl != null) {
      theMap.put("pageNavAddMoreToolsUrl", addMoreToolsUrl);
      theMap.put("pageNavCanAddMoreTools", true);
    } else {
      theMap.put("pageNavCanAddMoreTools", false);
    }

    theMap.put("pageNavTools", l);
    theMap.put(
        "pageMaxIfSingle",
        ServerConfigurationService.getBoolean("portal.experimental.maximizesinglepage", false));
    theMap.put("pageNavToolsCount", Integer.valueOf(l.size()));

    String helpUrl = ServerConfigurationService.getHelpUrl(null);
    theMap.put("pageNavShowHelp", Boolean.valueOf(showHelp));
    theMap.put("pageNavHelpUrl", helpUrl);
    theMap.put("helpMenuClass", "icon-sakai-help");
    theMap.put("subsiteClass", "icon-sakai-subsite");

    // theMap.put("pageNavSitContentshead",
    // Web.escapeHtml(rb.getString("sit_contentshead")));

    // Display presence? Global property display.users.present may be always / never / true / false
    // If true or false, the value may be overriden by the site property display-users-present
    // which may be true or false.

    boolean showPresence;
    String globalShowPresence =
        ServerConfigurationService.getString("display.users.present", "true");

    if ("never".equals(globalShowPresence)) {
      showPresence = false;
    } else if ("always".equals(globalShowPresence)) {
      showPresence = true;
    } else {
      String showPresenceSite = site.getProperties().getProperty("display-users-present");

      if (showPresenceSite == null) {
        showPresence = Boolean.valueOf(globalShowPresence).booleanValue();
      } else {
        showPresence = Boolean.valueOf(showPresenceSite).booleanValue();
      }
    }

    // Check to see if this is a my workspace site, and if so, whether presence is disabled
    if (showPresence
        && SiteService.isUserSite(site.getId())
        && !ServerConfigurationService.getBoolean("display.users.present.myworkspace", false))
      showPresence = false;

    String presenceUrl = Web.returnUrl(req, "/presence/" + Web.escapeUrl(site.getId()));

    // theMap.put("pageNavSitPresenceTitle",
    // Web.escapeHtml(rb.getString("sit_presencetitle")));
    // theMap.put("pageNavSitPresenceFrameTitle",
    // Web.escapeHtml(rb.getString("sit_presenceiframetit")));
    theMap.put("pageNavShowPresenceLoggedIn", Boolean.valueOf(showPresence && loggedIn));
    theMap.put("pageNavPresenceUrl", presenceUrl);

    // Retrieve whether or not we are to put presence in a frame
    theMap.put(
        "pageNavPresenceIframe",
        Boolean.valueOf(
            ServerConfigurationService.getBoolean("display.users.present.iframe", false)));
    theMap.put(
        "sakaiPresenceTimeDelay",
        Integer.valueOf(
            ServerConfigurationService.getInt("display.users.present.time.delay", 3000)));

    return theMap;
  }
  private String addOrCreateTool(Map payload, boolean trustedConsumer, User user, Site site)
      throws LTIException {
    // Check if the site already has the tool
    String toolPlacementId = null;
    String tool_id = (String) payload.get("tool_id");
    try {
      site = SiteService.getSite(site.getId());
      ToolConfiguration toolConfig = site.getToolForCommonId(tool_id);
      if (toolConfig != null) {
        toolPlacementId = toolConfig.getId();
      }
    } catch (Exception e) {
      M_log.warn(e.getLocalizedMessage(), e);
      throw new LTIException("launch.tool.search", "tool_id=" + tool_id, e);
    }

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

    // If tool not in site, and we are a trusted consumer, error
    // Otherwise, add tool to the site
    ToolConfiguration toolConfig = null;
    if (BasicLTIUtil.isBlank(toolPlacementId)) {
      try {
        SitePage sitePageEdit = null;
        sitePageEdit = site.addPage();
        sitePageEdit.setTitle(tool_id);

        toolConfig = sitePageEdit.addTool();
        toolConfig.setTool(tool_id, ToolManager.getTool(tool_id));
        toolConfig.setTitle(tool_id);

        Properties propsedit = toolConfig.getPlacementConfig();
        propsedit.setProperty(
            BASICLTI_RESOURCE_LINK, (String) payload.get(BasicLTIConstants.RESOURCE_LINK_ID));
        pushAdvisor();
        try {
          SiteService.save(site);
          M_log.info("Tool added, tool_id=" + tool_id + ", siteId=" + site.getId());
        } catch (Exception e) {
          throw new LTIException(
              "launch.site.save", "tool_id=" + tool_id + ", siteId=" + site.getId(), e);
        } finally {
          popAdvisor();
        }
        toolPlacementId = toolConfig.getId();

      } catch (Exception e) {
        throw new LTIException(
            "launch.tool.add", "tool_id=" + tool_id + ", siteId=" + site.getId(), e);
      }
    }

    // Get ToolConfiguration for tool if not already setup
    if (toolConfig == null) {
      toolConfig = site.getToolForCommonId(tool_id);
    }

    // Check user has access to this tool in this site
    if (!ToolManager.isVisible(site, toolConfig)) {
      M_log.warn(
          "Not allowed to access tool user_id="
              + user.getId()
              + " site="
              + site.getId()
              + " tool="
              + tool_id);
      throw new LTIException(
          "launch.site.tool.denied",
          "user_id=" + user.getId() + " site=" + site.getId() + " tool=" + tool_id,
          null);
    }
    return toolPlacementId;
  }
  public void findAllPages(
      SimplePageItem pageItem,
      List<PageEntry> entries,
      Map<Long, SimplePage> pageMap,
      Set<Long> topLevelPages,
      Set<Long> sharedPages,
      int level,
      boolean toplevel,
      boolean canEditPage) {
    // System.out.println("in findallpages " + pageItem.getName() + " " + toplevel);
    Long pageId = Long.valueOf(pageItem.getSakaiId());

    if (pageId == 0L) return;

    try {
      if (pageItem.isPrerequisite() || simplePageBean.getItemGroups(pageItem, null, false) != null)
        somePagesHavePrerequisites = true;
    } catch (IdUnusedException exe) {
      // underlying item missing. should be impossible for a page
      return;
    }

    // implement hidden.
    if (!canEditPage) {
      SimplePage page = simplePageToolDao.getPage(pageId);
      if (page.isHidden()) return;
      if (page.getReleaseDate() != null && page.getReleaseDate().after(new Date())) return;
      if (toplevel) {
        if (page.getToolId() != null) {
          // getCurrentSite is cached, so it's reasonable to get it at this level
          Site site = simplePageBean.getCurrentSite();
          SitePage sitePage = site.getPage(page.getToolId());
          List<ToolConfiguration> tools = sitePage.getTools();
          // If all the tools on a page require site.upd then only users with site.upd will see
          // the page in the site nav of Charon... not sure about the other Sakai portals floating
          // about
          boolean visible = false;
          for (ToolConfiguration placement : tools) {
            Properties roleConfig = placement.getPlacementConfig();
            String roleList = roleConfig.getProperty("functions.require");
            String visibility = roleConfig.getProperty("sakai-portal:visible");
            // System.out.println("roles " + roleList + " visi " + visibility);
            // doesn't require site update, so visible
            if ((visibility == null || !visibility.equals("false"))
                && (roleList == null || roleList.indexOf(SITE_UPD) < 0)) {
              // only need one tool on the page to be visible
              visible = true;
              break;
            }
          }

          // not visible, ignore it
          if (!visible) return;
        }
      }
    }

    PageEntry entry = new PageEntry();
    entry.pageId = pageId;
    entry.itemId = pageItem.getId();
    entry.title = pageItem.getName();
    entry.level = level;
    entry.toplevel = toplevel;

    // add entry
    entries.add(entry);

    // if page has already been done, don't do the subpages. Otherwise we can
    // get into infinite loops

    // already done if removed from map.
    // however for top level pages, expand them for their primary entry,
    // i.e. when toplevel is set.
    if (pageMap.get(pageId) == null || (topLevelPages.contains(pageId) && !toplevel)) {
      sharedPages.add(pageId);
      return;
    }

    // say done
    pageMap.remove(pageId);

    // now recursively do subpages

    List<SimplePageItem> items = simplePageToolDao.findItemsOnPage(pageId);
    List<SimplePageItem> nexts = new ArrayList<SimplePageItem>();

    // subpages done in place
    for (SimplePageItem item : items) {
      if (item.getType() == SimplePageItem.PAGE) {
        Long pageNum = Long.valueOf(item.getSakaiId());

        // ignore top-level pages.

        // show next pages (including top level pages) after all the subpages
        // so stick it on the delayed display list.
        if (item.getNextPage()) nexts.add(item);
        else {
          // System.out.println("call for subpage " + item.getName() + " " + false);
          findAllPages(
              item, entries, pageMap, topLevelPages, sharedPages, level + 1, false, canEditPage);
        }
      }
    }
    // nexts done afterwards
    for (SimplePageItem item : nexts) {
      if (item.getType() == SimplePageItem.PAGE) {
        // System.out.println("calling findallpage " + item.getName() + " " + false);
        findAllPages(item, entries, pageMap, topLevelPages, sharedPages, level, false, canEditPage);
      }
    }
  }
  /** Handle the configure context's update button */
  public void doConfigure_update(RunData data, Context context) {
    // TODO: if we do limit the initState() calls, we need to make sure we get a new one after this
    // call -ggolden

    String peid = ((JetspeedRunData) data).getJs_peid();
    SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);

    Placement placement = ToolManager.getCurrentPlacement();

    // get the site toolConfiguration, if this is part of a site.
    ToolConfiguration toolConfig = SiteService.findTool(placement.getId());

    // height
    String height = data.getParameters().getString(HEIGHT);
    if (height.equals(rb.getString("gen.heisomelse"))) {
      String customHeight = data.getParameters().getString(CUSTOM_HEIGHT);
      if ((customHeight != null) && (!customHeight.equals(""))) {
        if (!checkDigits(customHeight)) {
          addAlert(state, rb.getString("java.alert.pleentval"));
          return;
        }
        state.setAttribute(HEIGHT, customHeight);
        height = customHeight + "px";
        state.setAttribute(HEIGHT, height);
        placement.getPlacementConfig().setProperty(HEIGHT, height);
      } else {
        addAlert(state, rb.getString("java.alert.pleentval"));
        return;
      }
    } else if (SPECIAL_ANNOTATEDURL.equals(state.getAttribute(SPECIAL))) {
      // update the site info
      try {
        String desp = data.getParameters().getString("description");
        state.setAttribute(ANNOTATED_TEXT, desp);
        placement.getPlacementConfig().setProperty(ANNOTATED_TEXT, desp);

      } catch (Throwable e) {
      }
    } else {
      state.setAttribute(HEIGHT, height);
      placement.getPlacementConfig().setProperty(HEIGHT, height);
    }

    // title
    String title = data.getParameters().getString(TITLE);
    if (StringUtils.isBlank(title)) {
      addAlert(state, rb.getString("gen.tootit.empty"));
      return;
      // SAK-19515 check for LENGTH of tool title
    } else if (title.length() > MAX_TITLE_LENGTH) {
      addAlert(state, rb.getString("gen.tootit.toolong"));
      return;
    }
    placement.setTitle(title);

    // site info url
    String infoUrl = StringUtils.trimToNull(data.getParameters().getString("infourl"));
    if (infoUrl != null && infoUrl.length() > MAX_SITE_INFO_URL_LENGTH) {
      addAlert(state, rb.getString("gen.info.url.toolong"));
      return;
    }

    try {
      Site site = SiteService.getSite(toolConfig.getSiteId());
      SitePage page = site.getPage(toolConfig.getPageId());
      page.setTitleCustom(true);

      // for web content tool, if it is a site page tool, and the only tool on the page, update the
      // page title / popup.
      if ((state.getAttribute(SPECIAL) == null) && (toolConfig != null)) {
        // if this is the only tool on that page, update the page's title also
        if ((page.getTools() != null) && (page.getTools().size() == 1)) {
          String newPageTitle = data.getParameters().getString(FORM_PAGE_TITLE);

          if (StringUtils.isBlank(newPageTitle)) {
            addAlert(state, rb.getString("gen.pagtit.empty"));
            return;
          } else if (newPageTitle.length() > MAX_TITLE_LENGTH) {
            addAlert(state, rb.getString("gen.pagtit.toolong"));
            return;
          }
          page.setTitle(newPageTitle);
          state.setAttribute(STATE_PAGE_TITLE, newPageTitle);

          // popup
          boolean popup = data.getParameters().getBoolean("popup");
          page.setPopup(popup);
        }
      }

      SiteService.save(site);
    } catch (Exception ignore) {
      M_log.warn("doConfigure_update: " + ignore);
    }

    // read source if we are not special
    if (state.getAttribute(SPECIAL) == null) {
      String source = StringUtils.trimToEmpty(data.getParameters().getString(SOURCE));

      // User entered nothing in the source box; give the user an alert
      if (StringUtils.isBlank(source)) {
        addAlert(state, rb.getString("gen.url.empty"));
        return;
      }

      if ((!source.startsWith("/")) && (source.indexOf("://") == -1)) {
        source = "http://" + source;
      }

      // Validate the url
      UrlValidator urlValidator = new UrlValidator();
      if (!urlValidator.isValid(source)) {
        addAlert(state, rb.getString("gen.url.invalid"));
        return;
      }

      // update state
      placement.getPlacementConfig().setProperty(SOURCE, source);
    } else if (SPECIAL_WORKSITE.equals(state.getAttribute(SPECIAL))) {
      if ((infoUrl != null)
          && (infoUrl.length() > 0)
          && (!infoUrl.startsWith("/"))
          && (infoUrl.indexOf("://") == -1)) {
        infoUrl = "http://" + infoUrl;
      }
      String description = StringUtils.trimToNull(data.getParameters().getString("description"));
      description = FormattedText.processEscapedHtml(description);

      // update the site info
      try {
        SiteService.saveSiteInfo(
            ToolManager.getCurrentPlacement().getContext(), description, infoUrl);
      } catch (Throwable e) {
        M_log.warn("doConfigure_update: " + e);
      }
    }

    // save
    // TODO: we might have just saved the entire site, so this would not be needed -ggolden
    placement.save();

    // we are done with customization... back to the main mode
    state.removeAttribute(STATE_MODE);

    // refresh the whole page, since popup and title may have changed
    scheduleTopRefresh();
  }
  /** Setup the velocity context and choose the template for options. */
  public String buildOptionsPanelContext(
      VelocityPortlet portlet, Context context, RunData data, SessionState state) {
    // provide the source, and let the user edit, if not special
    String special = (String) state.getAttribute(SPECIAL);
    String source = "";
    String siteId = "";
    if (special == null) {
      source = (String) state.getAttribute(SOURCE);
      if (source == null) source = "";
      context.put(SOURCE, source);
      context.put("heading", rb.getString("gen.custom"));
    }

    // set the heading based on special
    else {
      if (SPECIAL_SITE.equals(special)) {
        context.put("heading", rb.getString("gen.custom.site"));
      } else if (SPECIAL_WORKSPACE.equals(special)) {
        context.put("heading", rb.getString("gen.custom.workspace"));
      } else if (SPECIAL_WORKSITE.equals(special)) {
        context.put("heading", rb.getString("gen.custom.worksite"));

        // for worksite, also include the Site's infourl and description
        try {
          Site s = SiteService.getSite(ToolManager.getCurrentPlacement().getContext());
          siteId = s.getId();

          String infoUrl = StringUtils.trimToNull(s.getInfoUrl());
          if (infoUrl != null) {
            context.put("info_url", infoUrl);
          }

          String description = StringUtils.trimToNull(s.getDescription());
          if (description != null) {
            description = FormattedText.escapeHtmlFormattedTextarea(description);
            context.put("description", description);
          }
        } catch (Throwable e) {
        }
      } else if (SPECIAL_ANNOTATEDURL.equals(special)) {

        context.put("heading", rb.getString("gen.custom.annotatedurl"));

        // for Annotated URL Tool page, also include the description
        try {
          String desp = state.getAttribute(ANNOTATED_TEXT).toString();
          context.put("description", desp);

        } catch (Throwable e) {
        }
      } else {
        context.put("heading", rb.getString("gen.custom"));
      }
    }

    boolean selected = false;
    String height = state.getAttribute(HEIGHT).toString();
    for (int i = 0; i < ourPixels.length; i++) {
      if (height.equals(ourPixels[i])) {
        selected = true;
        continue;
      }
    }
    if (!selected) {
      String[] strings = height.trim().split("px");
      context.put("custom_height", strings[0]);
      height = rb.getString("gen.heisomelse");
    }
    context.put(HEIGHT, height);

    context.put(TITLE, state.getAttribute(TITLE));
    context.put("tlang", rb);

    context.put("doUpdate", BUTTON + "doConfigure_update");
    context.put("doCancel", BUTTON + "doCancel");

    context.put("form_tool_title", FORM_TOOL_TITLE);
    context.put("form_page_title", FORM_PAGE_TITLE);

    // if we are part of a site, and the only tool on the page, offer the popup to edit
    Placement placement = ToolManager.getCurrentPlacement();
    ToolConfiguration toolConfig = SiteService.findTool(placement.getId());
    if ((state.getAttribute(SPECIAL) == null) && (toolConfig != null)) {
      try {
        Site site = SiteService.getSite(toolConfig.getSiteId());
        siteId = site.getId();
        SitePage page = site.getPage(toolConfig.getPageId());

        // if this is the only tool on that page, update the page's title also
        if ((page.getTools() != null) && (page.getTools().size() == 1)) {
          context.put("showPopup", Boolean.TRUE);
          context.put("popup", Boolean.valueOf(page.isPopUp()));

          context.put("pageTitleEditable", Boolean.TRUE);
          context.put("page_title", (String) state.getAttribute(STATE_PAGE_TITLE));
        }
      } catch (Throwable e) {
      }
    }

    // pick the "-customize" template based on the standard template name
    String template = (String) getContext(data).get("template");

    // pick the site customize template if we are in that mode
    if (SPECIAL_WORKSITE.equals(special)) {
      template = template + "-site-customize";
    } else if (SPECIAL_WORKSPACE.equals(special)) {
      template = template + "-customize";
    } else if (SPECIAL_ANNOTATEDURL.equals(special)) {
      template = template + "-annotatedurl-customize";
    } else {
      template = template + "-customize";
    }

    // tracking event
    if (siteId.length() == 0) {
      try {
        Site s = SiteService.getSite(ToolManager.getCurrentPlacement().getContext());
        siteId = s.getId();
      } catch (Throwable e) {

      }
    }
    if (special == null) {
      if (state.getAttribute(EVENT_REVISE_WEB_CONTENT) == null) {

        // this is a Web Content tool
        m_eventTrackingService.post(
            m_eventTrackingService.newEvent(
                EVENT_REVISE_WEB_CONTENT, source, siteId, true, NotificationService.NOTI_NONE));
      } else {
        // event in tool registration file will be used
        m_eventTrackingService.post(
            m_eventTrackingService.newEvent(
                (String) state.getAttribute(EVENT_REVISE_WEB_CONTENT),
                source,
                siteId,
                true,
                NotificationService.NOTI_NONE));
      }
    } else {
      if (state.getAttribute(EVENT_REVISE_WEB_CONTENT) != null) {
        // special and event in tool registration file
        m_eventTrackingService.post(
            m_eventTrackingService.newEvent(
                (String) state.getAttribute(EVENT_REVISE_WEB_CONTENT),
                source,
                siteId,
                true,
                NotificationService.NOTI_NONE));
      }
    }

    // output the max limit
    context.put("max_length_title", MAX_TITLE_LENGTH);
    context.put("max_length_info_url", MAX_SITE_INFO_URL_LENGTH);

    return template;
  }
  /** Populate the state with configuration settings */
  protected void initState(SessionState state, VelocityPortlet portlet, JetspeedRunData rundata) {
    // TODO: we might want to keep this from running for each request - but by letting it we get
    // fresh info each time... -ggolden
    super.initState(state, portlet, rundata);

    Placement placement = ToolManager.getCurrentPlacement();
    Properties config = placement.getConfig();

    // set the pass_pid parameter
    boolean passPid = false;
    String passPidStr = config.getProperty(PASS_PID, "false");
    state.removeAttribute(PASS_PID);
    if ("true".equalsIgnoreCase(passPidStr)) {
      state.setAttribute(PASS_PID, Boolean.TRUE);
      passPid = true;
    }

    // Assume macro expansion (disable on request)
    boolean macroExpansion = true;
    String macroExpansionStr = config.getProperty(MACRO_EXPANSION, "true");

    state.removeAttribute(MACRO_EXPANSION);
    if ("false".equalsIgnoreCase(macroExpansionStr)) {
      state.setAttribute(MACRO_EXPANSION, Boolean.FALSE);
      macroExpansion = false;
    }

    // set the special setting
    String special = config.getProperty(SPECIAL);

    final String sakaiPropertiesUrlKey = config.getProperty(SAKAI_PROPERTIES_URL_KEY);

    final String hideOptions = config.getProperty(HIDE_OPTIONS);

    // check for an older way the ChefWebPagePortlet took parameters, converting to our "special"
    // values
    if (special == null) {
      if ("true".equals(config.getProperty("site"))) {
        special = SPECIAL_SITE;
      } else if ("true".equals(config.getProperty("workspace"))) {
        special = SPECIAL_WORKSPACE;
      } else if ("true".equals(config.getProperty("worksite"))) {
        special = SPECIAL_WORKSITE;
      } else if ("true".equals(config.getProperty("annotatedurl"))) {
        special = SPECIAL_ANNOTATEDURL;
      }
    }

    state.removeAttribute(SPECIAL);
    if ((special != null) && (special.trim().length() > 0)) {
      state.setAttribute(SPECIAL, special);
    }

    state.removeAttribute(HIDE_OPTIONS);
    if ((hideOptions != null) && (hideOptions.trim().length() > 0)) {
      state.setAttribute(HIDE_OPTIONS, hideOptions);
    }

    // set the source url setting
    String source = StringUtils.trimToNull(config.getProperty(SOURCE));

    // check for an older way the ChefWebPagePortlet took parameters, converting to our "source"
    // value
    if (source == null) {
      source = StringUtils.trimToNull(config.getProperty("url"));
    }

    // store the raw as-configured source url
    state.removeAttribute(SOURCE);
    if (source != null) {
      state.setAttribute(SOURCE, source);
    }

    // compute working URL, modified from the configuration URL if special
    String url =
        sourceUrl(
            special,
            source,
            placement.getContext(),
            macroExpansion,
            passPid,
            placement.getId(),
            sakaiPropertiesUrlKey);
    state.setAttribute(URL, url);

    // set the height
    state.setAttribute(HEIGHT, config.getProperty(HEIGHT, "600px"));

    state.setAttribute(ANNOTATED_TEXT, config.getProperty(ANNOTATED_TEXT, ""));

    if (config.getProperty(TARGETPAGE_URL) != null) {
      // set Target page url for Annotated URL Tool
      state.setAttribute(TARGETPAGE_URL, config.getProperty(TARGETPAGE_URL));

      // set Target page name for Annotated URL Tool
      state.setAttribute(TARGETPAGE_NAME, config.getProperty(TARGETPAGE_NAME));
    }

    // set the title
    state.setAttribute(TITLE, placement.getTitle());

    if (state.getAttribute(STATE_PAGE_TITLE) == null) {
      SitePage p = SiteService.findPage(getCurrentSitePageId());
      state.setAttribute(STATE_PAGE_TITLE, p.getTitle());
    }

    // if events found in tool registration file put them in state
    if ((StringUtils.trimToNull(config.getProperty(EVENT_ACCESS_WEB_CONTENT)) != null)) {
      state.setAttribute(EVENT_ACCESS_WEB_CONTENT, config.getProperty(EVENT_ACCESS_WEB_CONTENT));
    }
    if ((StringUtils.trimToNull(config.getProperty(EVENT_REVISE_WEB_CONTENT)) != null)) {
      state.setAttribute(EVENT_REVISE_WEB_CONTENT, config.getProperty(EVENT_REVISE_WEB_CONTENT));
    }

    if (m_eventTrackingService == null) {
      m_eventTrackingService =
          (EventTrackingService)
              ComponentManager.get("org.sakaiproject.event.api.EventTrackingService");
    }
  }