/**
   * Process the blog entries
   *
   * @param httpServletRequest Request
   * @param httpServletResponse Response
   * @param blog {@link Blog} instance
   * @param context Context
   * @param entries Blog entries retrieved for the particular request
   * @return Modified set of blog entries
   * @throws PluginException If there is an error processing the blog entries
   */
  public Entry[] process(
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse,
      Blog blog,
      Map context,
      Entry[] entries)
      throws PluginException {
    Map entriesPerCategory = new HashMap();

    try {
      Category[] categories = (Category[]) context.get(BlojsomConstants.BLOJSOM_ALL_CATEGORIES);
      if (categories != null && categories.length > 0) {
        for (int i = 0; i < categories.length; i++) {
          Category category = categories[i];
          entriesPerCategory.put(
              category.getId(), _fetcher.countEntriesForCategory(blog, category));
        }
      }
    } catch (FetcherException e) {
      if (_logger.isErrorEnabled()) {
        _logger.error(e);
      }
    }

    context.put(PLUGIN_CONTEXT_ENTRIES_PER_CATEGORY, entriesPerCategory);

    return entries;
  }
  /**
   * Setup the comment e-mail
   *
   * @param blog {@link Blog} information
   * @param entry {@link Entry}
   * @param email Email message
   * @throws EmailException If there is an error preparing the e-mail message
   */
  protected void setupEmail(Blog blog, Entry entry, Email email) throws EmailException {
    email.setCharset(BlojsomConstants.UTF8);

    // If we have a mail session for the environment, use that
    if (_session != null) {
      email.setMailSession(_session);
    } else {
      // Otherwise, if there is a username and password for the mail server, use that
      if (!BlojsomUtils.checkNullOrBlank(_mailServerUsername)
          && !BlojsomUtils.checkNullOrBlank(_mailServerPassword)) {
        email.setHostName(_mailServer);
        email.setAuthentication(_mailServerUsername, _mailServerPassword);
      } else {
        email.setHostName(_mailServer);
      }
    }

    email.setFrom(blog.getBlogOwnerEmail(), "Blojsom Comment");

    String author = entry.getAuthor();
    if (BlojsomUtils.checkNullOrBlank(author)) {
      author = blog.getBlogOwner();
    }

    String authorEmail = blog.getBlogOwnerEmail();

    if (author != null) {
      try {
        User user = _fetcher.loadUser(blog, author);

        if (user == null) {
          authorEmail = blog.getBlogOwnerEmail();
        } else {
          authorEmail = user.getUserEmail();
          if (BlojsomUtils.checkNullOrBlank(authorEmail)) {
            authorEmail = blog.getBlogOwnerEmail();
          }
        }
      } catch (FetcherException e) {
      }
    }

    email.addTo(authorEmail, author);
    email.setSentDate(new Date());
  }
  /**
   * Process the blog entries
   *
   * @param httpServletRequest Request
   * @param httpServletResponse Response
   * @param blog {@link Blog} instance
   * @param context Context
   * @param entries Blog entries retrieved for the particular request
   * @return Modified set of blog entries
   * @throws org.blojsom.plugin.PluginException If there is an error processing the blog entries
   */
  public Entry[] process(
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse,
      Blog blog,
      Map context,
      Entry[] entries)
      throws PluginException {
    entries = super.process(httpServletRequest, httpServletResponse, blog, context, entries);
    String page = BlojsomUtils.getRequestValue(BlojsomConstants.PAGE_PARAM, httpServletRequest);

    String username = getUsernameFromSession(httpServletRequest, blog);
    if (!checkPermission(blog, null, username, SWITCH_THEME_PERMISSION)) {
      httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, ADMIN_ADMINISTRATION_PAGE);
      addOperationResultMessage(
          context,
          getAdminResource(
              FAILED_PERMISSION_KEY, FAILED_PERMISSION_KEY, blog.getBlogAdministrationLocale()));

      return entries;
    }

    if (ADMIN_LOGIN_PAGE.equals(page)) {
      return entries;
    } else {
      String action = BlojsomUtils.getRequestValue(ACTION_PARAM, httpServletRequest);

      context.put(THEME_SWITCHER_PLUGIN_AVAILABLE_THEMES, getAvailableThemes());
      context.put(THEME_SWITCHER_PLUGIN_FLAVORS, new TreeMap(blog.getTemplates()));
      context.put(THEME_SWITCHER_PLUGIN_DEFAULT_FLAVOR, blog.getBlogDefaultFlavor());
      String currentHtmlFlavor =
          (String) blog.getTemplates().get(BlojsomConstants.DEFAULT_FLAVOR_HTML);
      currentHtmlFlavor = currentHtmlFlavor.substring(0, currentHtmlFlavor.indexOf('.'));
      context.put(CURRENT_HTML_THEME, currentHtmlFlavor);

      if (SWITCH_THEME_ACTION.equals(action)) {
        String theme = BlojsomUtils.getRequestValue(THEME, httpServletRequest);
        String flavor = BlojsomUtils.getRequestValue(FLAVOR, httpServletRequest);

        if (BlojsomUtils.checkNullOrBlank(theme) || BlojsomUtils.checkNullOrBlank(flavor)) {
          addOperationResultMessage(
              context,
              getAdminResource(
                  NONE_SELECTED_KEY, NONE_SELECTED_KEY, blog.getBlogAdministrationLocale()));
          return entries;
        }

        if ("admin".equalsIgnoreCase(flavor)) {
          addOperationResultMessage(
              context,
              getAdminResource(
                  ADMIN_FLAVOR_PROTECTED_KEY,
                  ADMIN_FLAVOR_PROTECTED_KEY,
                  blog.getBlogAdministrationLocale()));
          return entries;
        }

        File copyFromTemplatesDirectory =
            new File(
                _servletConfig.getServletContext().getRealPath("/")
                    + BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
                    + _themesDirectory
                    + theme
                    + "/"
                    + _blojsomProperties.getProperty(BlojsomConstants.TEMPLATES_DIRECTORY_IP));

        File[] templateFiles = copyFromTemplatesDirectory.listFiles();
        String mainTemplate = null;

        if (templateFiles != null && templateFiles.length > 0) {
          for (int i = 0; i < templateFiles.length; i++) {
            File templateFile = templateFiles[i];
            if (!templateFile.isDirectory()) {
              if (templateFile.getName().startsWith(theme + ".")) {
                mainTemplate = templateFile.getName();
              }
            }
          }
        }

        File copyToTemplatesDirectory =
            new File(
                _servletConfig.getServletContext().getRealPath("/")
                    + BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
                    + _blojsomProperties.getProperty(BlojsomConstants.BLOGS_DIRECTORY_IP)
                    + blog.getBlogId()
                    + "/"
                    + _blojsomProperties.getProperty(BlojsomConstants.TEMPLATES_DIRECTORY_IP));

        try {
          BlojsomUtils.copyDirectory(copyFromTemplatesDirectory, copyToTemplatesDirectory);
        } catch (IOException e) {
          _logger.error(e);
          addOperationResultMessage(
              context,
              getAdminResource(
                  FAILED_THEME_TEMPLATE_COPY_KEY,
                  FAILED_THEME_TEMPLATE_COPY_KEY,
                  blog.getBlogAdministrationLocale()));
        }

        File copyFromResourcesDirectory =
            new File(
                _servletConfig.getServletContext().getRealPath("/")
                    + BlojsomConstants.DEFAULT_CONFIGURATION_BASE_DIRECTORY
                    + _themesDirectory
                    + theme
                    + "/"
                    + _blojsomProperties.getProperty(BlojsomConstants.RESOURCES_DIRECTORY_IP));
        File copyToResourcesDirectory =
            new File(
                _servletConfig.getServletContext().getRealPath("/")
                    + _blojsomProperties.getProperty(BlojsomConstants.RESOURCES_DIRECTORY_IP)
                    + blog.getBlogId()
                    + "/");

        try {
          BlojsomUtils.copyDirectory(copyFromResourcesDirectory, copyToResourcesDirectory);
        } catch (IOException e) {
          _logger.error(e);
          addOperationResultMessage(
              context,
              getAdminResource(
                  FAILED_THEME_TEMPLATE_COPY_KEY,
                  FAILED_THEME_TEMPLATE_COPY_KEY,
                  blog.getBlogAdministrationLocale()));
        }

        try {
          if (mainTemplate == null) {
            mainTemplate = (String) blog.getTemplates().get(flavor);

            _logger.debug(
                "No main template supplied for "
                    + theme
                    + " theme. Using existing template for flavor: "
                    + mainTemplate);
          } else {
            if (BlojsomConstants.DEFAULT_FLAVOR_HTML.equals(flavor)) {
              mainTemplate += ", " + "text/html;charset=UTF-8";
            }
          }

          Map templates = new HashMap(blog.getTemplates());
          templates.put(flavor, mainTemplate);
          blog.setTemplates(templates);

          _fetcher.saveBlog(blog);
        } catch (FetcherException e) {
          _logger.error(e);
          addOperationResultMessage(
              context,
              getAdminResource(
                  FAILED_FLAVOR_WRITE_KEY,
                  FAILED_FLAVOR_WRITE_KEY,
                  blog.getBlogAdministrationLocale()));

          return entries;
        }

        currentHtmlFlavor = (String) blog.getTemplates().get(BlojsomConstants.DEFAULT_FLAVOR_HTML);
        currentHtmlFlavor = currentHtmlFlavor.substring(0, currentHtmlFlavor.indexOf('.'));
        context.put(CURRENT_HTML_THEME, currentHtmlFlavor);

        addOperationResultMessage(
            context,
            formatAdminResource(
                THEME_SWITCHED_KEY,
                THEME_SWITCHED_KEY,
                blog.getBlogAdministrationLocale(),
                new Object[] {theme, flavor}));
        _eventBroadcaster.processEvent(
            new ProcessRequestEvent(
                this, new Date(), blog, httpServletRequest, httpServletResponse, context));
      } else {
        _eventBroadcaster.processEvent(
            new ProcessRequestEvent(
                this, new Date(), blog, httpServletRequest, httpServletResponse, context));

        context.put(THEME_SWITCHER_PLUGIN_AVAILABLE_THEMES, getAvailableThemes());
      }
    }

    return entries;
  }
  /**
   * Add a comment to a particular blog entry
   *
   * @param author Comment author
   * @param authorEmail Comment author e-mail
   * @param authorURL Comment author URL
   * @param userComment Comment
   * @param blogCommentsEnabled If comments are enabled or not
   * @param commentMetaData Metadata for the comment
   * @param blog {@link Blog}
   * @param entry {@link Entry}
   * @param httpServletRequest {@link HttpServletRequest}
   * @return BlogComment Entry
   */
  private Comment addBlogComment(
      String author,
      String authorEmail,
      String authorURL,
      String userComment,
      boolean blogCommentsEnabled,
      Map commentMetaData,
      Blog blog,
      Entry entry,
      HttpServletRequest httpServletRequest) {
    Comment comment = null;

    if (blogCommentsEnabled) {
      try {
        comment = _fetcher.newComment();
        comment.setBlogEntryId(entry.getId());
        comment.setEntry(entry);
        comment.setAuthor(author);
        comment.setAuthorEmail(authorEmail);
        comment.setAuthorURL(authorURL);
        comment.setComment(userComment);
        comment.setCommentDate(new Date());
        comment.setBlogId(blog.getId());
        comment.setIp(httpServletRequest.getRemoteAddr());
        if (commentMetaData.containsKey(
                CommentModerationPlugin.BLOJSOM_COMMENT_MODERATION_PLUGIN_APPROVED)
            && "true"
                .equals(
                    commentMetaData.get(
                        CommentModerationPlugin.BLOJSOM_COMMENT_MODERATION_PLUGIN_APPROVED))) {
          comment.setStatus(ResponseConstants.APPROVED_STATUS);
        } else {
          if ("true".equals(blog.getProperty(CommentModerationPlugin.COMMENT_MODERATION_ENABLED))) {
            comment.setStatus(ResponseConstants.NEW_STATUS);
          } else {
            comment.setStatus(ResponseConstants.APPROVED_STATUS);
          }
        }
        comment.setMetaData(commentMetaData);

        String commentParentID =
            BlojsomUtils.getRequestValue(COMMENT_PARENT_ID, httpServletRequest);
        if (!BlojsomUtils.checkNullOrBlank(commentParentID)) {
          try {
            comment.setParentId(Integer.valueOf(commentParentID));
          } catch (NumberFormatException e) {
          }
        }

        _fetcher.saveComment(blog, comment);
      } catch (FetcherException e) {
        if (_logger.isErrorEnabled()) {
          _logger.error(e);
        }

        comment = null;
      }
    }

    return comment;
  }
  /**
   * Process the blog entries
   *
   * @param httpServletRequest Request
   * @param httpServletResponse Response
   * @param blog {@link Blog} instance
   * @param context Context
   * @param entries Blog entries retrieved for the particular request
   * @return Modified set of blog entries
   * @throws PluginException If there is an error processing the blog entries
   */
  public Entry[] process(
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse,
      Blog blog,
      Map context,
      Entry[] entries)
      throws PluginException {
    context.put(BLOJSOM_COMMENT_PLUGIN_ENABLED, blog.getBlogCommentsEnabled());
    if (!blog.getBlogCommentsEnabled().booleanValue()) {
      if (_logger.isDebugEnabled()) {
        _logger.debug("Comments not enabled for blog: " + blog.getBlogId());
      }

      return entries;
    }

    Boolean _blogCommentsEnabled;
    _blogCommentsEnabled = blog.getBlogCommentsEnabled();

    int _cookieExpiration;
    String cookieExpiration = blog.getProperty(COMMENT_COOKIE_EXPIRATION_DURATION_IP);
    if (BlojsomUtils.checkNullOrBlank(cookieExpiration)) {
      _cookieExpiration = COOKIE_EXPIRATION_AGE;
    } else {
      try {
        _cookieExpiration = Integer.parseInt(cookieExpiration);
      } catch (NumberFormatException e) {
        _cookieExpiration = COOKIE_EXPIRATION_AGE;
      }
    }

    if (entries.length == 0) {
      return entries;
    }

    String author = httpServletRequest.getParameter(AUTHOR_PARAM);
    String authorEmail = httpServletRequest.getParameter(AUTHOR_EMAIL_PARAM);
    String authorURL = httpServletRequest.getParameter(AUTHOR_URL_PARAM);
    String rememberMe = httpServletRequest.getParameter(REMEMBER_ME_PARAM);

    // Check to see if the person has requested they be "remembered" and if so
    // extract their information from the appropriate cookies
    Cookie authorCookie = CookieUtils.getCookie(httpServletRequest, COOKIE_AUTHOR);
    if ((authorCookie != null) && BlojsomUtils.checkNullOrBlank(author)) {
      author = authorCookie.getValue();
      if (_logger.isDebugEnabled()) {
        _logger.debug("Pulling author from cookie: " + author);
      }

      if ("".equals(author)) {
        author = null;
      } else {
        context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR, author);
      }

      Cookie authorEmailCookie = CookieUtils.getCookie(httpServletRequest, COOKIE_EMAIL);
      if ((authorEmailCookie != null) && BlojsomUtils.checkNullOrBlank(authorEmail)) {
        authorEmail = authorEmailCookie.getValue();
        if (_logger.isDebugEnabled()) {
          _logger.debug("Pulling author email from cookie: " + authorEmail);
        }

        if (authorEmail == null) {
          authorEmail = "";
        } else {
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_EMAIL, authorEmail);
        }
      }

      Cookie authorUrlCookie = CookieUtils.getCookie(httpServletRequest, COOKIE_URL);
      if ((authorUrlCookie != null) && BlojsomUtils.checkNullOrBlank(authorURL)) {
        authorURL = authorUrlCookie.getValue();
        if (_logger.isDebugEnabled()) {
          _logger.debug("Pulling author URL from cookie: " + authorURL);
        }

        if (authorURL == null) {
          authorURL = "";
        } else {
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_URL, authorURL);
        }
      }

      Cookie rememberMeCookie = CookieUtils.getCookie(httpServletRequest, COOKIE_REMEMBER_ME);
      if ((rememberMeCookie != null) && ((rememberMe == null) || "".equals(rememberMe))) {
        rememberMe = rememberMeCookie.getValue();
        if (rememberMe != null) {
          context.put(BLOJSOM_COMMENT_PLUGIN_REMEMBER_ME, rememberMe);
        }
      }
    }

    String remoteIPAddress = httpServletRequest.getRemoteAddr();

    // Comment handling
    if ("y".equalsIgnoreCase(httpServletRequest.getParameter(COMMENT_PARAM))
        && _blogCommentsEnabled.booleanValue()) {
      String commentText = httpServletRequest.getParameter(COMMENT_TEXT_PARAM);
      String remember = httpServletRequest.getParameter(REMEMBER_ME_PARAM);

      if (!BlojsomUtils.checkNullOrBlank(author) && !BlojsomUtils.checkNullOrBlank(commentText)) {
        // Check for comment throttling
        String commentThrottleValue = blog.getProperty(COMMENT_THROTTLE_MINUTES_IP);
        if (!BlojsomUtils.checkNullOrBlank(commentThrottleValue)) {
          int commentThrottleMinutes;

          try {
            commentThrottleMinutes = Integer.parseInt(commentThrottleValue);
          } catch (NumberFormatException e) {
            commentThrottleMinutes = COMMENT_THROTTLE_DEFAULT_MINUTES;
          }
          if (_logger.isDebugEnabled()) {
            _logger.debug("Comment throttling enabled at: " + commentThrottleMinutes + " minutes");
          }

          if (_ipAddressCommentTimes.containsKey(remoteIPAddress)) {
            Calendar currentTime = Calendar.getInstance();
            Calendar timeOfLastComment = (Calendar) _ipAddressCommentTimes.get(remoteIPAddress);
            long timeDifference =
                currentTime.getTimeInMillis() - timeOfLastComment.getTimeInMillis();

            long differenceInMinutes = timeDifference / (60 * 1000);
            if (differenceInMinutes < commentThrottleMinutes) {
              if (_logger.isDebugEnabled()) {
                _logger.debug(
                    "Comment throttle enabled. Comment from IP address: "
                        + remoteIPAddress
                        + " in less than "
                        + commentThrottleMinutes
                        + " minutes");
              }

              return entries;
            } else {
              if (_logger.isDebugEnabled()) {
                _logger.debug(
                    "Comment throttle enabled. Resetting date of last comment to current time");
              }

              _ipAddressCommentTimes.put(remoteIPAddress, currentTime);
            }
          } else {
            Calendar calendar = Calendar.getInstance();
            _ipAddressCommentTimes.put(remoteIPAddress, calendar);
          }
        }

        author = author.trim();
        author = BlojsomUtils.escapeStringSimple(author);
        author = BlojsomUtils.stripLineTerminators(author, " ");

        commentText = commentText.trim();

        // Check if autoformatting of comment text should be done
        boolean autoformatComments =
            Boolean.valueOf(blog.getProperty(COMMENT_AUTOFORMAT_IP)).booleanValue();
        if (autoformatComments) {
          commentText = BlojsomUtils.replace(commentText, "\n", "<br />");
        }

        if (authorEmail != null) {
          authorEmail = authorEmail.trim();
          authorEmail = BlojsomUtils.escapeStringSimple(authorEmail);
          authorEmail = BlojsomUtils.stripLineTerminators(authorEmail, " ");
        } else {
          authorEmail = "";
        }

        if (authorURL != null) {
          authorURL = authorURL.trim();
          authorURL = BlojsomUtils.escapeStringSimple(authorURL);
          authorURL = BlojsomUtils.stripLineTerminators(authorURL, " ");
        } else {
          authorURL = "";
        }

        if (!BlojsomUtils.checkNullOrBlank(authorURL)
            && !authorURL.toLowerCase().startsWith("http://")) {
          authorURL = "http://" + authorURL;
        }

        Entry entryForComment = _fetcher.newEntry();
        try {
          String blogEntryId = BlojsomUtils.getRequestValue("entry_id", httpServletRequest);
          Integer entryId;
          try {
            entryId = Integer.valueOf(blogEntryId);
          } catch (NumberFormatException e) {
            if (_logger.isErrorEnabled()) {
              _logger.error(e);
            }

            return entries;
          }

          entryForComment.setId(entryId);

          _fetcher.loadEntry(blog, entryForComment);
          if (_logger.isDebugEnabled()) {
            _logger.debug("Loaded entry for comment: " + entryId.toString());
          }

          if (entryForComment.allowsComments().booleanValue()) {
            // Check for a comment where the number of days between comment auto-expiration has
            // passed
            String commentDaysExpiration = blog.getProperty(COMMENT_DAYS_EXPIRATION_IP);
            if (!BlojsomUtils.checkNullOrBlank(commentDaysExpiration)) {
              try {
                int daysExpiration = Integer.parseInt(commentDaysExpiration);
                int daysBetweenDates =
                    BlojsomUtils.daysBetweenDates(entryForComment.getDate(), new Date());
                if ((daysExpiration > 0) && (daysBetweenDates >= daysExpiration)) {
                  if (_logger.isDebugEnabled()) {
                    _logger.debug(
                        "Comment period for this entry has expired. Expiration period set at "
                            + daysExpiration
                            + " days. Difference in days: "
                            + daysBetweenDates);
                  }

                  return entries;
                }
              } catch (NumberFormatException e) {
                if (_logger.isErrorEnabled()) {
                  _logger.error(
                      "Error in parameter "
                          + COMMENT_DAYS_EXPIRATION_IP
                          + ": "
                          + commentDaysExpiration);
                }
              }
            }
          } else {
            if (_logger.isDebugEnabled()) {
              _logger.debug(
                  "Comments have been disabled for blog entry: " + entryForComment.getId());
            }

            return entries;
          }
        } catch (FetcherException e) {
          if (_logger.isErrorEnabled()) {
            _logger.error(e);
          }

          return entries;
        }

        Map commentMetaData = new HashMap();

        // Check to see if a previous plugin populated meta-data for the comment
        if (context.containsKey(BLOJSOM_PLUGIN_COMMENT_METADATA)) {
          Map metaData = (Map) context.get(BLOJSOM_PLUGIN_COMMENT_METADATA);

          Iterator metaDataKeys = metaData.keySet().iterator();
          Object key;
          Object value;
          while (metaDataKeys.hasNext()) {
            key = metaDataKeys.next();
            value = metaData.get(key);
            commentMetaData.put(key, value);
          }
        }

        CommentResponseSubmissionEvent commentResponseSubmissionEvent =
            new CommentResponseSubmissionEvent(
                this,
                new Date(),
                blog,
                httpServletRequest,
                httpServletResponse,
                author,
                authorEmail,
                authorURL,
                commentText,
                entryForComment,
                commentMetaData);
        _eventBroadcaster.processEvent(commentResponseSubmissionEvent);
        author = commentResponseSubmissionEvent.getSubmitter();
        authorEmail = commentResponseSubmissionEvent.getSubmitterItem1();
        authorURL = commentResponseSubmissionEvent.getSubmitterItem2();
        commentText = commentResponseSubmissionEvent.getContent();

        // Check to see if the comment should be destroyed (not saved) automatically
        if (!commentMetaData.containsKey(BLOJSOM_PLUGIN_COMMENT_METADATA_DESTROY)) {
          Comment comment =
              addBlogComment(
                  author,
                  authorEmail,
                  authorURL,
                  commentText,
                  _blogCommentsEnabled.booleanValue(),
                  commentMetaData,
                  blog,
                  entries[0],
                  httpServletRequest);

          // For persisting the Last-Modified time
          context.put(BlojsomConstants.BLOJSOM_LAST_MODIFIED, new Long(new Date().getTime()));

          if (comment != null) {
            context.put(BLOJSOM_COMMENT_PLUGIN_STATUS, comment.getStatus());

            try {
              _fetcher.loadEntry(blog, entries[0]);
              _fetcher.loadEntry(blog, entryForComment);
              _eventBroadcaster.broadcastEvent(
                  new CommentAddedEvent(this, new Date(), comment, blog));
            } catch (FetcherException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
          } else {
            context.put(BLOJSOM_COMMENT_PLUGIN_STATUS, BLOJSOM_COMMENT_PLUGIN_STATUS_ERROR);
          }
        } else {
          if (_logger.isDebugEnabled()) {
            _logger.debug("Comment meta-data contained destroy key. Comment was not saved");
          }

          context.put(BLOJSOM_COMMENT_PLUGIN_STATUS, ResponseConstants.DELETED_STATUS);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR, author);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_EMAIL, authorEmail);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_URL, authorURL);
          if (autoformatComments) {
            context.put(
                BLOJSOM_COMMENT_PLUGIN_COMMENT_TEXT,
                BlojsomUtils.escapeStringSimple(BlojsomUtils.replace(commentText, "<br />", "\n")));
          } else {
            context.put(
                BLOJSOM_COMMENT_PLUGIN_COMMENT_TEXT, BlojsomUtils.escapeStringSimple(commentText));
          }
        }

        // If we're asked to remember the person, then add the appropriate cookies
        if ((remember != null) && (!"".equals(remember))) {
          CookieUtils.addCookie(httpServletResponse, _cookieExpiration, COOKIE_AUTHOR, author);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR, author);
          CookieUtils.addCookie(httpServletResponse, _cookieExpiration, COOKIE_EMAIL, authorEmail);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_EMAIL, authorEmail);
          CookieUtils.addCookie(httpServletResponse, _cookieExpiration, COOKIE_URL, authorURL);
          context.put(BLOJSOM_COMMENT_PLUGIN_AUTHOR_URL, authorURL);
          CookieUtils.addCookie(httpServletResponse, _cookieExpiration, COOKIE_REMEMBER_ME, "true");
          context.put(BLOJSOM_COMMENT_PLUGIN_REMEMBER_ME, "true");
        }
      }

      String redirectTo =
          BlojsomUtils.getRequestValue(BlojsomConstants.REDIRECT_TO_PARAM, httpServletRequest);
      if (!BlojsomUtils.checkNullOrBlank(redirectTo)) {
        try {
          httpServletResponse.sendRedirect(BlojsomUtils.urlEncodeForLink(redirectTo));
          httpServletRequest.setAttribute(BlojsomConstants.IS_IN_REDIRECT, Boolean.TRUE);
        } catch (IOException e) {
        }
      }
    }

    return entries;
  }
  /**
   * Process the blog entries
   *
   * @param httpServletRequest Request
   * @param httpServletResponse Response
   * @param blog {@link Blog} instance
   * @param context Context
   * @param entries Blog entries retrieved for the particular request
   * @return Modified set of blog entries
   * @throws PluginException If there is an error processing the blog entries
   */
  public Entry[] process(
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse,
      Blog blog,
      Map context,
      Entry[] entries)
      throws PluginException {
    entries = super.process(httpServletRequest, httpServletResponse, blog, context, entries);

    String page = BlojsomUtils.getRequestValue(BlojsomConstants.PAGE_PARAM, httpServletRequest);

    String username = getUsernameFromSession(httpServletRequest, blog);
    if (!checkPermission(blog, null, username, IP_MODERATION_PERMISSION)) {
      httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, ADMIN_ADMINISTRATION_PAGE);
      addOperationResultMessage(
          context,
          getAdminResource(
              FAILED_IP_ADDRESS_MODERATION_PERMISSION_KEY,
              FAILED_IP_ADDRESS_MODERATION_PERMISSION_KEY,
              blog.getBlogAdministrationLocale()));

      return entries;
    }

    if (ADMIN_LOGIN_PAGE.equals(page)) {
      return entries;
    } else {
      String action = BlojsomUtils.getRequestValue(ACTION_PARAM, httpServletRequest);
      List ipAddressesFromBlacklist = loadIPList(blog, IP_BLACKLIST_IP);
      List ipAddressesFromWhitelist = loadIPList(blog, IP_WHITELIST_IP);
      String listType = BlojsomUtils.getRequestValue(LIST_TYPE, httpServletRequest);

      if (ADD_IP_ADDRESS_ACTION.equals(action)) {
        String ipAddress = BlojsomUtils.getRequestValue(IP_ADDRESS, httpServletRequest);

        if (BLACKLIST.equals(listType)) {
          if (!ipAddressesFromBlacklist.contains(ipAddress)) {
            ipAddressesFromBlacklist.add(ipAddress);
            blog.setProperty(
                IP_BLACKLIST_IP, BlojsomUtils.listToString(ipAddressesFromBlacklist, "\n"));
            try {
              _fetcher.saveBlog(blog);
            } catch (FetcherException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
            addOperationResultMessage(
                context,
                formatAdminResource(
                    ADDED_IP_TO_BLACKLIST_KEY,
                    ADDED_IP_TO_BLACKLIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {ipAddress}));
          } else {
            addOperationResultMessage(
                context,
                formatAdminResource(
                    IP_ALREADY_ADDED_TO_BLACKLIST_KEY,
                    IP_ALREADY_ADDED_TO_BLACKLIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {ipAddress}));
          }
        } else {
          if (!ipAddressesFromWhitelist.contains(ipAddress)) {
            ipAddressesFromWhitelist.add(ipAddress);
            blog.setProperty(
                IP_WHITELIST_IP, BlojsomUtils.listToString(ipAddressesFromWhitelist, "\n"));
            try {
              _fetcher.saveBlog(blog);
            } catch (FetcherException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
            addOperationResultMessage(
                context,
                formatAdminResource(
                    ADDED_IP_TO_WHITELIST_KEY,
                    ADDED_IP_TO_WHITELIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {ipAddress}));
          } else {
            addOperationResultMessage(
                context,
                formatAdminResource(
                    IP_ALREADY_ADDED_TO_WHITELIST_KEY,
                    IP_ALREADY_ADDED_TO_WHITELIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {ipAddress}));
          }
        }
      } else if (DELETE_IP_ADDRESS_ACTION.equals(action)) {
        String[] ipAddressesToDelete = httpServletRequest.getParameterValues(IP_ADDRESS);

        if (ipAddressesToDelete != null && ipAddressesToDelete.length > 0) {
          if (BLACKLIST.equals(listType)) {
            for (int i = 0; i < ipAddressesToDelete.length; i++) {
              ipAddressesFromBlacklist.set(Integer.parseInt(ipAddressesToDelete[i]), null);
            }

            ipAddressesFromBlacklist = BlojsomUtils.removeNullValues(ipAddressesFromBlacklist);
            blog.setProperty(
                IP_BLACKLIST_IP, BlojsomUtils.listToString(ipAddressesFromBlacklist, "\n"));
            try {
              _fetcher.saveBlog(blog);
            } catch (FetcherException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
            addOperationResultMessage(
                context,
                formatAdminResource(
                    DELETED_IP_ADDRESSES_BLACKLIST_KEY,
                    DELETED_IP_ADDRESSES_BLACKLIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {new Integer(ipAddressesToDelete.length)}));
          } else {
            for (int i = 0; i < ipAddressesToDelete.length; i++) {
              ipAddressesFromWhitelist.set(Integer.parseInt(ipAddressesToDelete[i]), null);
            }

            ipAddressesFromWhitelist = BlojsomUtils.removeNullValues(ipAddressesFromWhitelist);
            blog.setProperty(
                IP_WHITELIST_IP, BlojsomUtils.listToString(ipAddressesFromWhitelist, "\n"));
            try {
              _fetcher.saveBlog(blog);
            } catch (FetcherException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
            addOperationResultMessage(
                context,
                formatAdminResource(
                    DELETED_IP_ADDRESSES_WHITELIST_KEY,
                    DELETED_IP_ADDRESSES_WHITELIST_KEY,
                    blog.getBlogAdministrationLocale(),
                    new Object[] {new Integer(ipAddressesToDelete.length)}));
          }
        } else {
          addOperationResultMessage(
              context,
              getAdminResource(
                  NO_IP_ADDRESSES_SELECTED_KEY,
                  NO_IP_ADDRESSES_SELECTED_KEY,
                  blog.getBlogAdministrationLocale()));
        }
      }

      context.put(BLOJSOM_PLUGIN_IP_BLACKLIST, ipAddressesFromBlacklist);
      context.put(BLOJSOM_PLUGIN_IP_WHITELIST, ipAddressesFromWhitelist);
    }

    return entries;
  }
  /**
   * Handle an event broadcast from another component
   *
   * @param event {@link Event} to be handled
   */
  public void handleEvent(Event event) {
    if (!BlojsomUtils.checkNullOrBlank(_twitterUpdateURL)) {
      if ((event instanceof EntryAddedEvent) || (event instanceof EntryUpdatedEvent)) {
        EntryEvent entryEvent = (EntryEvent) event;

        Blog blog = entryEvent.getBlog();
        String author = entryEvent.getEntry().getAuthor();
        User user;

        try {
          user = _fetcher.loadUser(blog, author);
        } catch (FetcherException e) {
          if (_logger.isErrorEnabled()) {
            _logger.error("Error loading User object to retrieve Twitter properties", e);
          }

          return;
        }

        if (!BlojsomUtils.checkNullOrBlank((String) blog.getProperty(TWITTER_SIGN_IN_IP))
            && !BlojsomUtils.checkNullOrBlank((String) blog.getProperty(TWITTER_PASSWORD_IP))) {

          String signIn = (String) blog.getProperty(TWITTER_SIGN_IN_IP);
          String password = (String) blog.getProperty(TWITTER_PASSWORD_IP);
          String updateText = (String) blog.getProperty(TWITTER_STATUS_UPDATE_TEXT_IP);

          if (BlojsomUtils.checkNullOrBlank(updateText)) {
            updateText = TWITTER_DEFAULT_STATUS_UPDATE_TEXT;
          }

          if (("true".equals(blog.getProperty(TWITTER_UPDATE_ON_ENTRY_ADDED_IP)))
              || ("true".equals(blog.getProperty(TWITTER_UPDATE_ON_ENTRY_UPDATED_IP)))) {
            String title = entryEvent.getEntry().getTitle();
            String twitterUpdate =
                BlojsomUtils.urlEncode(
                    BlojsomUtils.escapeString(
                        MessageFormat.format(updateText, new Object[] {title})));

            Authenticator.setDefault(new TwitterAuthenticator(signIn, password));

            try {
              URL url = new URL(_twitterUpdateURL);
              URLConnection urlConnection = url.openConnection();
              urlConnection.setUseCaches(false);
              urlConnection.setDoInput(true);
              urlConnection.setDoOutput(true);
              urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

              String twitterData = TWITTER_STATUS_PARAMETER + "=" + twitterUpdate;
              OutputStreamWriter twitterWriter =
                  new OutputStreamWriter(urlConnection.getOutputStream());
              twitterWriter.write(twitterData);
              twitterWriter.flush();
              twitterWriter.close();

              // Read all the text returned by the server
              BufferedReader twitterReader =
                  new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
              StringBuffer twitterReply = new StringBuffer();
              String input;

              while ((input = twitterReader.readLine()) != null) {
                twitterReply.append(input);
              }

              twitterReader.close();

              if (BlojsomUtils.checkNullOrBlank(twitterReply.toString())) {
                if (_logger.isErrorEnabled()) {
                  _logger.error("Error communicating update to Twitter");
                }
              } else {
                if (_logger.isDebugEnabled()) {
                  _logger.debug("Successfully sent update to Twitter");
                }
              }
            } catch (IOException e) {
              if (_logger.isErrorEnabled()) {
                _logger.error(e);
              }
            }
          } else {
            if (_logger.isDebugEnabled()) {
              _logger.debug(
                  "Twitter notification update not enabled for either add or update entry events");
            }
          }
        } else {
          if (_logger.isDebugEnabled()) {
            _logger.debug("Twitter sign in and/or password is null or blank");
          }
        }
      }
    }
  }