public HtmlResponse performCommand(
      WCMCommandContext ctx,
      SlingHttpServletRequest request,
      SlingHttpServletResponse response,
      PageManager pageManager) {
    try {
      Page master = null;
      String srcPath = request.getParameter(WCMCommand.SRC_PATH_PARAM);
      if (StringUtils.isNotEmpty(srcPath)) {
        if (srcPath.endsWith("/jcr:content")) {
          srcPath = srcPath.substring(0, srcPath.length() - "/jcr:content".length());
        }
        master = pageManager.getPage(srcPath);
      }
      if (master == null) {
        return HtmlStatusResponseHelper.createStatusResponse(
            false, I18n.get(request, "Blueprint {0} not found.", "", srcPath));
      }

      boolean reset = "true".equals(request.getParameter(WCMCommand.FORCE_PARAM));

      String[] targets = request.getParameterValues(WCMCommand.DEST_PATH_PARAM);
      if (targets.length == 0) {
        return HtmlStatusResponseHelper.createStatusResponse(
            false, I18n.get(request, "No targets selected."));
      }

      int successCount = 0;
      int errorCount = 0;
      for (String target : targets) {
        try {
          Page targetPage = pageManager.getContainingPage(target);
          catalogGenerator.rolloutChanges(master, targetPage, reset);
          successCount++;
        } catch (Exception e) {
          log.error("Rollout failed for {}.", target, e);
          errorCount++;
        }
      }

      List<String> messages = new ArrayList<String>();
      messages.add(I18n.get(request, "Rollout Complete.  "));
      if (successCount > 0) {
        messages.add(I18n.get(request, "Rolled out changes to {0} catalogs.", "", successCount));
      }
      if (errorCount > 0) {
        messages.add(I18n.get(request, "Errors encountered in {0} catalogs.", "", errorCount));
      }
      return HtmlStatusResponseHelper.createStatusResponse(
          successCount > 0, messages.toArray(new String[messages.size()]), targets);
    } catch (Exception e) {
      String msg = I18n.get(request, "Error during rollout.");
      log.error(msg, e);
      return HtmlStatusResponseHelper.createStatusResponse(false, msg);
    }
  }
  @Override
  protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    HtmlResponse htmlResponse = null;
    ResourceResolver adminResolver = null;
    Session adminSession = null;

    try {
      String email = request.getParameter(REQ_PRM_USERNAME);
      String password = request.getParameter(REQ_PRM_PASSWORD);
      String inviteKey = request.getParameter(REQ_PRM_INVITEKEY);
      String acceptStatus = request.getParameter(REQ_PRM_ACCEPT_STATUS);

      adminResolver = getAdminResolver();
      adminSession = adminResolver.adaptTo(Session.class);

      InvitationToken invToken =
          ccInvitationService.getInvitationTokenByTokenKey(inviteKey, adminResolver);
      if (invToken != null && invToken.isValid() && inviteKey.equals(invToken.getKey())) {

        // Gets user account if user is already configured. Gets null
        // otherwise.
        Resource configResource = CCUtils.getAccountResourceByUserEmail(adminResolver, email);
        if (configResource == null) { // Create configuration if not
          // present. For first time login

          // encrypt the password
          if (!crypto.isProtected(password)) {
            password = crypto.protect(password);
          }
          AccessToken token = null;
          try {
            token = imsService.getAccessToken(email, password);
          } catch (Exception e) {
            log.error(e.getMessage(), e);
            htmlResponse =
                HtmlStatusResponseHelper.createStatusResponse(false, "Invalid Credentials");
          }
          if (token != null) { // succesful login
            String configName = "invited_" + email;
            configName = configName.replace("@", "_at_").replaceAll("\\.", "_");
            PageManager pageManager = pageManagerFactory.getPageManager(adminResolver);
            pageManager.create(CC_CONFIG_ROOT, configName, configName, CC_CONFIG_PAGE_TEMPLATE);

            Node configNode = adminSession.getNode(CC_CONFIG_ROOT + "/" + configName);
            Node contentNode = configNode.getNode("jcr:content");
            contentNode.setProperty(CreativeCloudAccountConfig.PROPERTY_USERNAME, email);
            contentNode.setProperty("sling:resourceType", CreativeCloudAccountConfig.RESOURCE_TYPE);

            contentNode.setProperty(
                CreativeCloudAccountConfig.PROPERTY_ACCESS_TOKEN, token.getAccessToken());
            contentNode.setProperty(
                CreativeCloudAccountConfig.PROPERTY_REFRESH_TOKEN, token.getRefreshToken());
            contentNode.setProperty(
                CreativeCloudAccountConfig.PROPERTY_TOKEN_EXPIRES, token.getExpiresIn());
            contentNode.setProperty(CreativeCloudAccountConfig.PROPERTY_PASSWORD, password);

            Node pollConfigNode = contentNode.addNode(CreativeCloudAccountConfig.NN_POLLCONFIG);
            pollConfigNode.setProperty(
                CreativeCloudAccountConfig.PROPERTY_INTERVAL, importer.getMinimumInterval());
            pollConfigNode.setProperty(CreativeCloudAccountConfig.PROPERTY_ENABLED, true);

            configResource = adminResolver.getResource(contentNode.getPath());
            ccConfigService.initAccount(configResource);
          }
        } else {
          // Sets the jcr content node as the config node
          configResource = configResource.getChild("jcr:content");
        }
        if (acceptStatus != null && acceptStatus.equalsIgnoreCase("false")) {
          htmlResponse = HtmlStatusResponseHelper.createStatusResponse(true, "invitation declined");
        } else {
          String[] paths = invToken.getPaths();
          for (String path : paths) {
            // ccShareService.shareWithCCUser(configResource,
            // adminResolver.getResource(path));
            // Asynchronous sharing
            Object job =
                new CCShareInBackground(factory, configResource.getPath(), path, ccShareService);
            String jobName =
                CCShareInBackground.class.getName()
                    + "_"
                    + UUID.randomUUID().toString().substring(0, 8);
            scheduler.fireJobAt(jobName, job, null, new Date());
          }
          htmlResponse = HtmlStatusResponseHelper.createStatusResponse(true, "invitation accepted");
        }
        ccInvitationService.acceptInvitation(email, inviteKey, adminResolver);
        adminSession.save();

      } else {
        htmlResponse =
            HtmlStatusResponseHelper.createStatusResponse(
                false, "invitation expired or already accepted/declined");
      }
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      htmlResponse = HtmlStatusResponseHelper.createStatusResponse(false, e.getMessage());
      htmlResponse.setError(e);
    } finally {
      if (adminSession != null) {
        adminSession.logout();
      }
      if (adminResolver != null) {
        adminResolver.close();
      }
      assert htmlResponse != null;
      htmlResponse.send(response, true);
    }
  }