private static Set<String> getZimletNames(List<Zimlet> zimlets) {
   Set<String> names = new LinkedHashSet<String>();
   for (Zimlet zimlet : zimlets) {
     names.add(zimlet.getName());
   }
   return names;
 }
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    if (!isHttpReq(request, response)) {
      return;
    }
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;

    AuthToken authToken;
    try {
      authToken = getAuthTokenForApp(req, resp, false);
    } catch (ServiceException se) {
      ZimbraLog.zimlet.info("can't get authToken: " + se.getMessage());
      resp.sendError(HttpServletResponse.SC_FORBIDDEN);
      return;
    }

    if (authToken == null) {
      // error was already sent out
      return;
    }

    boolean isAdminAuth = false;
    //		ZimbraLog.zimlet.info(">>> isAdminAuth: "+isAdminAuth);

    // get list of allowed zimlets
    Provisioning prov = Provisioning.getInstance();
    List<Zimlet> allowedZimlets = new LinkedList<Zimlet>();
    List<Zimlet> allZimlets = new LinkedList<Zimlet>();
    try {
      isAdminAuth =
          AdminAccessControl.getAdminAccessControl(authToken)
              .isSufficientAdminForZimletFilterServlet();

      // add all available zimlets
      if (!isAdminAuth) {
        // zimlets for this account's COS
        Account account = prov.get(AccountBy.id, authToken.getAccountId(), authToken);
        for (String zimletName : ZimletUtil.getAvailableZimlets(account).getZimletNamesAsArray()) {
          Zimlet zimlet = prov.getZimlet(zimletName);
          if (zimlet == null) continue;
          if (zimlet.isEnabled()) {
            allowedZimlets.add(zimlet);
          }
          allZimlets.add(zimlet);
        }
      }

      // add the admin zimlets
      else {
        allZimlets = prov.listAllZimlets();
        Iterator<Zimlet> iter = allZimlets.iterator();
        while (iter.hasNext()) {
          Zimlet zimlet = iter.next();
          if (zimlet.isExtension()) {
            if (zimlet.isEnabled()) {
              allowedZimlets.add(zimlet);
            }
          }
        }
      }
    } catch (ServiceException e) {
      ZimbraLog.zimlet.info("unable to get list of zimlets");
      resp.sendError(HttpServletResponse.SC_FORBIDDEN);
      return;
    }

    // order by priority
    List<Zimlet> zimletList = ZimletUtil.orderZimletsByPriority(allowedZimlets);
    Set<String> allowedZimletNames = getZimletNames(zimletList);
    Set<String> allZimletNames = getZimletNames(allZimlets);

    // get list of zimlets for request
    Set<String> zimletNames = new LinkedHashSet<String>();
    String uri = req.getRequestURI();
    boolean isZimletRes = uri.startsWith(ZIMLET_RES_URL_PREFIX);
    if (isZimletRes) {
      zimletNames.addAll(allowedZimletNames);
    } else {
      Matcher matcher = mPattern.matcher(uri);
      if (!matcher.matches()) {
        ZimbraLog.zimlet.info("no zimlet specified in request");
        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
      }
      zimletNames.add(matcher.group(1));
    }

    // check access
    File basedir = new File(LC.zimlet_directory.value());
    File devdir = new File(basedir, ZimletUtil.ZIMLET_DEV_DIR);
    Iterator<String> iter = zimletNames.iterator();
    while (iter.hasNext()) {
      String zimletName = iter.next();
      try {
        File devfile = new File(devdir, zimletName);
        if (devfile.exists()) {
          continue;
        }

        Zimlet zimlet = prov.getZimlet(zimletName);
        if (zimlet == null) {
          ZimbraLog.zimlet.info("no such zimlet: " + zimletName);
          iter.remove();
          allZimlets.remove(zimlet);
          continue;
        }

        if (!allowedZimletNames.contains(zimletName)) {
          ZimbraLog.zimlet.info(
              "unauthorized request to zimlet "
                  + zimletName
                  + " from user "
                  + authToken.getAccountId());
          iter.remove();
          allZimlets.remove(zimlet);
          continue;
        }

        if (zimlet.isExtension() && !isAdminAuth) {
          //					ZimbraLog.zimlet.info("!!!!! removing extension zimlet: "+zimletName);
          iter.remove();
          allZimlets.remove(zimlet);
        }
      } catch (ServiceException se) {
        ZimbraLog.zimlet.info(
            "service exception to zimlet "
                + zimletName
                + " from user "
                + authToken.getAccountId()
                + ": "
                + se.getMessage());
        iter.remove();
      }
    }

    if (!isZimletRes) {
      Matcher matcher = mPattern.matcher(uri);
      if (matcher.matches()) {
        String zimletName = matcher.group(1);
        if (!zimletNames.contains(zimletName)) {
          resp.sendError(HttpServletResponse.SC_FORBIDDEN);
          return;
        }
      }
    }

    // force compilation of template
    if (uri.endsWith(".template.js")) {
      Matcher matcher = mPattern.matcher(uri);
      if (matcher.matches()) {
        String zimletName = matcher.group(1);
        String opath = matcher.group(3);
        String ipath = opath.replaceAll(".js$", "");
        boolean isDevZimlet = uri.indexOf("_dev") != -1;
        File zimletDir = new File(isDevZimlet ? devdir : basedir, zimletName);
        File ifile = new File(zimletDir, ipath);
        File ofile = new File(zimletDir, opath);
        if (!ofile.exists() || (ifile.exists() && ifile.lastModified() > ofile.lastModified())) {
          String prefix = zimletName + ".";
          try {
            TemplateCompiler.compile(
                zimletDir, zimletDir, prefix, new String[] {ipath}, true, true);
          } catch (IOException e) {
            // ignore, let fail
          }
        }
      }
    }

    // process request
    req.setAttribute(ZimletFilter.ALLOWED_ZIMLETS, zimletNames);
    req.setAttribute(ZimletFilter.ALL_ZIMLETS, allZimletNames);
    chain.doFilter(req, resp);
  }