alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * $Header: /cvsroot/mvnforum/mvnforum/src/com/mvnforum/user/PostWebHandler.java,v 1.65.2.1 2005/05/20 08:52:56 minhnn Exp $
 * $Author: minhnn $
 * $Revision: 1.65.2.1 $
 * $Date: 2005/05/20 08:52:56 $
 *
 * ====================================================================
 *
 * Copyright (C) 2002-2005 by MyVietnam.net
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * All copyright notices regarding mvnForum MUST remain intact
 * in the scripts and in the outputted HTML.
 * The "powered by" text/logo with a link back to
 * http://www.mvnForum.com and http://www.MyVietnam.net in the
 * footer of the pages MUST remain visible when the pages
 * are viewed on the internet or intranet.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Support can be obtained from support forums at:
 * http://www.mvnForum.com/mvnforum/index
 *
 * Correspondence and Marketing Questions can be sent to:
 * info@MyVietnam.net
 *
 * @author: Minh Nguyen  minhnn@MyVietnam.net
 * @author: Mai  Nguyen  mai.nh@MyVietnam.net
 */
package com.mvnforum.user;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mvnforum.*;
import com.mvnforum.auth.*;
import com.mvnforum.common.StatisticsUtil;
import com.mvnforum.db.*;
import com.mvnforum.search.post.*;
import net.myvietnam.mvncore.exception.*;
import net.myvietnam.mvncore.filter.DisableHtmlTagFilter;
import net.myvietnam.mvncore.interceptor.InterceptorService;
import net.myvietnam.mvncore.security.FloodControl;
import net.myvietnam.mvncore.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

class PostWebHandler {

    private static Log log = LogFactory.getLog(PostWebHandler.class);

    private OnlineUserManager onlineUserManager = OnlineUserManager.getInstance();

    PostWebHandler() {
    }

    /**
     * This method is for addpost page
     */
    void prepareAdd(HttpServletRequest request, HttpServletResponse response)
        throws ObjectNotFoundException, DatabaseException, BadInputException, AuthenticationException, AssertionException {

        Locale locale = I18nUtil.getLocaleInRequest(request);

        if (MVNForumConfig.getEnableNewPost() == false) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_create_new_post.new_post_is_disabled");
            throw new AssertionException(localizedMessage);
            //throw new AssertionException("Cannot create new post because NEW_POST feature is disabled by administrator.");
        }
        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        if (MVNForumConfig.isGuestUserInDatabase() == false) {
            permission.ensureIsAuthenticated();
        }

        // we set this action attribute first because the return below can make method return prematurely
        request.setAttribute("action", "addnew");

        int parentPostID    = 0;
        try {
            // neu co parent thi` khong co forum !!!
            parentPostID = ParamUtil.getParameterInt(request, "parent");
        } catch (Exception ex) {
            // do nothing
            // NOTE: we cannot return here since user can have a parameter parent = 0
        }

        if (parentPostID == 0) {// new thread
            int forumID = ParamUtil.getParameterInt(request, "forum");

            ForumBean forumBean = null;
            try {
                forumBean = ForumCache.getInstance().getBean(forumID);
            } catch (ObjectNotFoundException e) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumBean.ensureNotDisabledForum();
            forumBean.ensureNotClosedForum();
            forumBean.ensureNotLockedForum();

            permission.ensureCanAddThread(forumID);
        } else {// reply to a post
            // this is a parent post
            PostBean postBean = null;
            try {
                postBean = DAOFactory.getPostDAO().getPost(parentPostID);// can throw DatabaseException
            } catch (ObjectNotFoundException ex) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(parentPostID)});
                throw new ObjectNotFoundException(localizedMessage);
            }

            // check permission
            int forumID  = postBean.getForumID();

            ForumBean forumBean = null;
            try {
                forumBean = ForumCache.getInstance().getBean(forumID);
            } catch (ObjectNotFoundException e) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumBean.ensureNotDisabledForum();
            forumBean.ensureNotClosedForum();
            forumBean.ensureNotLockedForum();

            permission.ensureCanAddPost(forumID);

            // now we prepare to list lastest post in the thread
            int threadID = postBean.getThreadID();

            // now check if thread is closed or locked, if it is, then cannot reply to a post
            ThreadBean threadBean = null;
            try {
                threadBean = DAOFactory.getThreadDAO().getThread(threadID);
            } catch ( ObjectNotFoundException ex ) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
                throw new ObjectNotFoundException(localizedMessage);
            }

            threadBean.ensureStatusCanReply();

            Collection postBeans = DAOFactory.getPostDAO().getLastEnablePosts_inThread_limit(threadID, MVNForumConfig.ROWS_IN_LAST_REPLIES);
            request.setAttribute("ParentPostBean", postBean);
            request.setAttribute("PostBeans", postBeans);
        }

        boolean isPreviewing = ParamUtil.getParameterBoolean(request, "preview");
        if (isPreviewing) {
            MyUtil.saveVNTyperMode(request, response);

            // Check if user enter some text or not
            ParamUtil.getParameter(request, "PostTopic", true);
            ParamUtil.getParameter(request, "message", true);// use message instead of MessageBody
            MemberBean memberBean = DAOFactory.getMemberDAO().getMember_forPublic(onlineUser.getMemberID());
            request.setAttribute("MemberBean", memberBean);
        }
    }

    void processAdd(HttpServletRequest request, HttpServletResponse response)
        throws ObjectNotFoundException, AssertionException, DatabaseException, CreateException,
        BadInputException, ForeignKeyNotFoundException, AuthenticationException, FloodException, InterceptorException {

        Locale locale = I18nUtil.getLocaleInRequest(request);
        if (MVNForumConfig.getEnableNewPost() == false) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_create_new_post.new_post_is_disabled");
            throw new AssertionException(localizedMessage);
            //throw new AssertionException("Cannot create new post because NEW_POST feature is disabled by administrator.");
        }

        String currentIP = request.getRemoteAddr();
        try {
            FloodControl.ensureNotReachMaximum(MVNForumGlobal.FLOOD_ID_NEW_POST, currentIP);
        } catch (FloodException fe) {
            //throw new FloodException("You have reached the maximum number of the post adding actions for this page. Please try this page later. This is to prevent forum from being flooded.");
            Integer maxPosts = new Integer(FloodControl.getActionsPerHour(MVNForumGlobal.FLOOD_ID_NEW_POST));
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.FloodException.add_post_too_many_times", new Object[] {maxPosts});
            throw new FloodException(localizedMessage);
        }
        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        MyUtil.saveVNTyperMode(request, response);

        int memberID      = onlineUser.getMemberID();
        String memberName = onlineUser.getMemberName();

        Timestamp now     = DateUtil.getCurrentGMTTimestamp();

        int parentPostID  = ParamUtil.getParameterInt(request, "parent");

        boolean attachMore  = ParamUtil.getParameterBoolean(request, "AttachMore");
        boolean addFavoriteThread = ParamUtil.getParameterBoolean(request, "AddFavoriteParentThread");
        boolean addWatchThread    = ParamUtil.getParameterBoolean(request, "AddWatchParentThread");

        String postTopic = ParamUtil.getParameter(request, "PostTopic", true);
        postTopic = DisableHtmlTagFilter.filter(postTopic);// always disable HTML
        InterceptorService.getInstance().validateContent(postTopic);

        String postBody = ParamUtil.getParameter(request, "message", true); // use message instead of MessageBody
        postBody = DisableHtmlTagFilter.filter(postBody);// always disable HTML
        InterceptorService.getInstance().validateContent(postBody);

        String postIcon = ParamUtil.getParameter(request, "PostIcon");
        postIcon = DisableHtmlTagFilter.filter(postIcon);// always disable HTML

        int forumID = 0;
        int threadID= 0;
        boolean isPendingThread = false;
        boolean isForumModerator = false;
        if (parentPostID == 0) {// new thread

            forumID = ParamUtil.getParameterInt(request, "forum");
            ForumBean forumBean = null;
            try {
                forumBean = ForumCache.getInstance().getBean(forumID);
            } catch (ObjectNotFoundException e) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumBean.ensureNotDisabledForum();
            forumBean.ensureNotClosedForum();
            forumBean.ensureNotLockedForum();

            // check permission
            isForumModerator = permission.canModerateThread(forumID);
            permission.ensureCanAddThread(forumID);

            String lastPostMemberName = memberName;

            int threadType = ParamUtil.getParameterUnsignedInt(request, "ThreadType", ThreadBean.THREAD_TYPE_DEFAULT);
            if ( threadType > ThreadBean.THREAD_TYPE_GLOBAL_ANNOUNCEMENT /* 3 */) {
                //threadType = 0;
                throw new BadInputException("Not support this thread type");
            }

            if (threadType == ThreadBean.THREAD_TYPE_GLOBAL_ANNOUNCEMENT) {
                permission.ensureCanAdminSystem();
                //forumID = -1; // this thread not belongs to any forum
            } else if (threadType != ThreadBean.THREAD_TYPE_DEFAULT ) {
                permission.ensureCanModerateThread(forumID);
            }

            int threadOption = 0; //@todo review and support it later
            int threadStatus = ThreadBean.THREAD_STATUS_DEFAULT;

            // Ensure that moderator dont have to moderate the thread to enable it
            if (forumBean.shouldModerateThread() && !isForumModerator) {
                threadStatus = ThreadBean.THREAD_STATUS_DISABLED;
                isPendingThread = true;
            }

            int threadHasPoll     = 0;//@todo review and support it later
            int threadDuration    = 0;//@todo review and support it later
            int threadAttachCount = 0;
            threadID = DAOFactory.getThreadDAO().createThread(forumID, memberName, lastPostMemberName,
                                   postTopic, postBody, 0/*threadVoteCount*/,
                                   0/*threadVoteTotalStars*/, now/*threadCreationDate*/, now/*threadLastPostDate*/,
                                   threadType, threadOption, threadStatus,
                                   threadHasPoll, 0/*threadViewCount*/, 0/*threadReplyCount*/,
                                   postIcon, threadDuration, threadAttachCount);
        } else {// reply to a post
            PostBean parentPostBean = null;
            try {
                parentPostBean = DAOFactory.getPostDAO().getPost(parentPostID);// can throw DatabaseException
            } catch (ObjectNotFoundException ex) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(parentPostID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumID = parentPostBean.getForumID();
            threadID = parentPostBean.getThreadID();

            ForumBean forumBean = null;
            try {
                forumBean = ForumCache.getInstance().getBean(forumID);
            } catch (ObjectNotFoundException e) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumBean.ensureNotDisabledForum();
            forumBean.ensureNotClosedForum();
            forumBean.ensureNotLockedForum();

            // check permission
            isForumModerator = permission.canModerateThread(forumID);
            permission.ensureCanAddPost(forumID);

            // now check if thread is closed or locked, if it is, then cannot reply to a post
            ThreadBean threadBean = null;
            try {
                threadBean = DAOFactory.getThreadDAO().getThread(threadID);
            } catch (ObjectNotFoundException ex ) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            threadBean.ensureStatusCanReply();
        }

        //Timestamp postLastEditDate = now;
        String postCreationIP       = currentIP;
        String postLastEditIP       = "";// should we init it to postCreationIP ???
        int postFormatOption        = 0;
        int postOption              = 0;
        int postStatus              = PostBean.POST_STATUS_DEFAULT;

        try {
            // Ensure that moderator dont have to moderate the thread to enable it
            if (ForumCache.getInstance().getBean(forumID).shouldModeratePost() && !isForumModerator) {
                // we will not disble post that is a thread (parentPostID == 0)
                if (parentPostID != 0) {// replied post
                    postStatus = PostBean.POST_STATUS_DISABLED;
                }
            }
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        int postAttachCount = 0;

        int postID = DAOFactory.getPostDAO().createPost(parentPostID, forumID, threadID,
                             memberID, memberName, ""/*lastEditMemberName*/,
                             postTopic, postBody, now/*postCreationDate*/,
                             now/*postLastEditDate*/, postCreationIP, postLastEditIP,
                             0/*postEditCount*/, postFormatOption, postOption,
                             postStatus, postIcon, postAttachCount);

        StatisticsUtil.updateMemberStatistics(memberID);
        StatisticsUtil.updateForumStatistics(forumID);
        StatisticsUtil.updateThreadStatistics(threadID);

        /** @todo Update PostEditLog table here */

        //add favorite thread if user checked it
        if (addFavoriteThread) {
            permission.ensureIsAuthenticated();
            //@todo: add checking of MVNForumConfig.getEnableFavoriteThread()
            // check to make sure that this user doesnt exceed his favorite max
            int currentFavoriteCount = DAOFactory.getFavoriteThreadDAO().getNumberOfFavoriteThreads_inMember(memberID);
            int maxFavorites = MVNForumConfig.getMaxFavoriteThread();
            if (currentFavoriteCount < maxFavorites) {
                Timestamp favoriteCreationDate = now;
                int favoriteType = 0; //@todo implement it later
                int favoriteOption = 0; //@todo implement it later
                int favoriteStatus = 0; //@todo implement it later

                // now check permission the this user have the readPost permission
                permission.ensureCanReadPost(forumID);

                // has the permission now, then insert to database
                try {
                    DAOFactory.getFavoriteThreadDAO().create(memberID, threadID, forumID,
                        favoriteCreationDate, favoriteType, favoriteOption,
                        favoriteStatus);
                } catch (DuplicateKeyException ex) {
                    // already add favorite thread, just ignore
                }
            }
        }

        //add watch if user checked it
        if (addWatchThread) {
            permission.ensureIsAuthenticated();
            permission.ensureIsActivated();
            if (MVNForumConfig.getEnableWatch() == false) {
                // should never happen, because if it happen, then the whole process is broken
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_add_watch.watch_is_disabled");
                throw new AssertionException(localizedMessage);
                //throw new AssertionException("Cannot add Watch because Watch feature is disabled by administrator.");
            }

            int watchType               = 0;//ParamUtil.getParameterInt(request, "WatchType");
            int watchOption             = 0;//ParamUtil.getParameterInt(request, "WatchOption");
            int watchStatus             = 0;//ParamUtil.getParameterInt(request, "WatchStatus");
            Timestamp watchCreationDate = now;
            Timestamp watchLastSentDate = now;
            Timestamp watchEndDate      = now;// @todo: check it !!!

            try {
                DAOFactory.getWatchDAO().create(memberID, 0/*watchCategoryID*/, 0/*watchForumID*/,
                                           threadID, watchType, watchOption,
                                           watchStatus, watchCreationDate, watchLastSentDate,
                                           watchEndDate);
            } catch (DuplicateKeyException ex) {
                // User try to create a duplicate watch, just ignore
            }
        }

        // now, update the Search Index
        //@todo check the performance here
        PostBean justAddedPostBean = null;
        try {
            justAddedPostBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        PostIndexer.scheduleAddPostTask(justAddedPostBean);

        request.setAttribute("PostBean", justAddedPostBean);
        request.setAttribute("ForumID", String.valueOf(forumID));
        request.setAttribute("ThreadID", String.valueOf(threadID));
        request.setAttribute("PostID", String.valueOf(postID));
        request.setAttribute("AttachMore", new Boolean(attachMore));
        request.setAttribute("AddFavoriteParentThread", new Boolean(addFavoriteThread));
        request.setAttribute("AddWatchParentThread", new Boolean(addWatchThread));
        request.setAttribute("IsPendingThread", new Boolean(isPendingThread));
        /**@todo: review, this variable is still reserved*/
        //request.setAttribute("ParentPostID", String.valueOf(parentPostID));

        FloodControl.increaseCount(MVNForumGlobal.FLOOD_ID_NEW_POST, currentIP);
    }

    void preparePrintPost(HttpServletRequest request)
        throws ObjectNotFoundException, DatabaseException, BadInputException,
        AuthenticationException, AssertionException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        int postID = ParamUtil.getParameterInt(request, "post");
        Locale locale = I18nUtil.getLocaleInRequest(request);

        PostBean postBean = null;
        try {
            postBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int threadID = postBean.getThreadID();
        int forumID = postBean.getForumID();

        try {
            ForumCache.getInstance().getBean(forumID).ensureNotDisabledForum();
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        permission.ensureCanReadPost(forumID);

        // to show the thread topic
        ThreadBean threadBean = null;
        try {
            threadBean = DAOFactory.getThreadDAO().getThread(threadID);
        } catch ( ObjectNotFoundException ex ) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        MemberBean memberBean = null;
        if (postBean.getMemberID() > 0) {
            memberBean = DAOFactory.getMemberDAO().getMember_forPublic(postBean.getMemberID());
        }
        postBean.setMemberBean(memberBean);

        int postAttachCount = postBean.getPostAttachCount();
        if ( (postAttachCount > 0) && MVNForumConfig.getEnableAttachment()) {
            Collection attachBeans = DAOFactory.getAttachmentDAO().getAttachments_inPost(postID);
            int actualAttachCount = attachBeans.size();

            // now check if the attachCount in talbe Post equals to the actual attachCount in table Attachment
            if (postAttachCount != actualAttachCount) {
                if (actualAttachCount != DAOFactory.getAttachmentDAO().getNumberOfAttachments_inPost(postID)) {
                    String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.serious_error.cannot_process_attachment_count");
                    throw new AssertionException(localizedMessage);
                    //throw new AssertionException("AssertionException: Serious error: cannot process Attachment Count in table Attachment");
                }
                log.warn("The attachment count in table Post and Attachment are not synchronized. In table Post = " + postAttachCount + " and in table Attachment = " + actualAttachCount + ". Synchronize to " + actualAttachCount);
                DAOFactory.getPostDAO().updateAttachCount(postID, actualAttachCount);
            }
            if (actualAttachCount > 0) {
                postBean.setAttachmentBeans(attachBeans);
            }
        }

        request.setAttribute("PostBean", postBean);
        request.setAttribute("ThreadBean", threadBean);
    }

    /**
     * then, it will be forward to addpost.jsp
     * NOTE: This method MUST NOT use parameter MessageParent (need some process to figure out)
     */
    void prepareEdit(HttpServletRequest request)
        throws ObjectNotFoundException, DatabaseException, BadInputException, AuthenticationException, AssertionException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        // a guest CANNOT edit a post, because it need Authenticated Permission
        permission.ensureIsAuthenticated();
        Locale locale = I18nUtil.getLocaleInRequest(request);

        int postID = ParamUtil.getParameterInt(request, "post");
        PostBean postBean = null;
        try {
            postBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int forumID = postBean.getForumID();

        ForumBean forumBean = null;
        try {
            forumBean = ForumCache.getInstance().getBean(forumID);
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        forumBean.ensureNotDisabledForum();
        forumBean.ensureNotLockedForum();

        // now check if thread is closed or locked, if it is, then cannot reply to a post
        int threadID = postBean.getThreadID();
        ThreadBean threadBean = null;
        try {
            threadBean = DAOFactory.getThreadDAO().getThread(threadID);
        } catch ( ObjectNotFoundException ex ) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        threadBean.ensureStatusCanEdit();

        int logonMemberID = onlineUser.getMemberID();
        int authorID      = postBean.getMemberID();

        // check constraint
        if (permission.canEditPost(forumID)) {
            // have permission, just do nothing, that is dont check the max day contraint
        } else if (logonMemberID == authorID) {// same author
            // check date here, usually must not older than 7 days
            Timestamp now = DateUtil.getCurrentGMTTimestamp();
            Timestamp postDate = postBean.getPostCreationDate();
            int maxDays = MVNForumConfig.getMaxEditDays();
            if ( (now.getTime() - postDate.getTime()) > (DateUtil.DAY * maxDays) ) {
                /** @todo choose a better Exception here */
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_edit.post_is_too_old", new Object[] {new Integer(maxDays)});
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("You cannot edit a post which is older than " + maxDays + " days.");
            }
            /** @todo check status of this post */
            /*
            if (postBean.getPostStatus() == ?) {
                throw new BadInputException("Cannot edit message which is disable.");
            }*/
        } else {//not an author, so this user must have Edit Permission
            permission.ensureCanEditPost(forumID);// this method ALWAYS throws AuthenticationException
        }

        request.setAttribute("PostToEdit", postBean);
        request.setAttribute("action", "update");

        boolean isPreviewing = ParamUtil.getParameterBoolean(request, "preview");
        if (isPreviewing) {
            // Check if user enter some text or not
            ParamUtil.getParameter(request, "PostTopic", true);
            ParamUtil.getParameter(request, "message", true);// use message instead of MessageBody

            MemberBean memberBean = DAOFactory.getMemberDAO().getMember_forPublic(onlineUser.getMemberID());
            request.setAttribute("MemberBean", memberBean);
        }
    }

    /**
     * @todo: log the modification
     * @todo: check the comment below, it's obsolete now :(
     * @todo: check coi messageTopic co the la optional khi reply
     * NOTE: This method MUST NOT get parameter MessageParent (need some process to figure out)
     *      so it needs to call setAttribute with messageParent for page updatepostsuccess.jsp
     */
    void processUpdate(HttpServletRequest request)
        throws ObjectNotFoundException, BadInputException, DatabaseException, CreateException,
               ForeignKeyNotFoundException, AuthenticationException, AssertionException, InterceptorException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        // a guest CANNOT edit a post, because it need Authenticated Permission
        permission.ensureIsAuthenticated();
        Locale locale = I18nUtil.getLocaleInRequest(request);

        Timestamp now   = DateUtil.getCurrentGMTTimestamp();

        int postID      = ParamUtil.getParameterInt(request, "post");// dont change

        // check constraint
        PostBean postBean = null;
        try {
            postBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int forumID = postBean.getForumID();
        int threadID = postBean.getThreadID();

        ForumBean forumBean = ForumCache.getInstance().getBean(forumID);
        forumBean.ensureNotDisabledForum();
        forumBean.ensureNotLockedForum();

        // now check if thread is locked, if it is, then cannot reply to a post
        // Please note that if the threadStatus is closed, post can still be edited
        ThreadBean threadBean = null;
        try {
            threadBean = DAOFactory.getThreadDAO().getThread(threadID);
        } catch ( ObjectNotFoundException ex ) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        threadBean.ensureStatusCanEdit();

        String postTopic  = ParamUtil.getParameter(request, "PostTopic", true);
        postTopic = DisableHtmlTagFilter.filter(postTopic);// always disable HTML
        InterceptorService.getInstance().validateContent(postTopic);

        String postBody   = ParamUtil.getParameter(request, "message", true);// use message instead of PostBody
        postBody = DisableHtmlTagFilter.filter(postBody);// always disable HTML
        InterceptorService.getInstance().validateContent(postBody);

        int    logonMemberID    = onlineUser.getMemberID();
        String logonMemberName  = onlineUser.getMemberName();
        int    authorID         = postBean.getMemberID();

        // check constraint
        if (permission.canEditPost(forumID)) {
            // have permission, just do nothing, that is dont check the max day contraint
        } else if (logonMemberID == authorID) {// same author
            // check date here, usually must not older than 7 days
            Timestamp postDate = postBean.getPostCreationDate();
            int maxDays = MVNForumConfig.getMaxEditDays();
            if ( (now.getTime() - postDate.getTime()) > (DateUtil.DAY * maxDays) ) {
                /** @todo choose a better Exception here */
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_edit.post_is_too_old", new Object[] {new Integer(maxDays)});
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("You cannot edit a post which is older than " + maxDays + " days.");
            }
            /** @todo check status of this post */
            /*
            if (postBean.getPostStatus() == ?) {
                throw new BadInputException("Cannot edit a post which is disable.");
            }*/
        } else {//not an author, so this user must have Edit Permission
            permission.ensureCanEditPost(forumID);// this method ALWAYS throws AuthenticationException
        }

        String postLastEditIP       = request.getRemoteAddr();
        int postFormatOption        = 0;//@todo review and support it later
        int postOption              = 0;//@todo review and support it later
        int postStatus              = postBean.getPostStatus();// use old post status
        String postIcon = ParamUtil.getParameter(request, "PostIcon");
        postIcon = DisableHtmlTagFilter.filter(postIcon);// always disable HTML

        /*
         * Note that although the 2 methods below can be combined,
         * I dont do that for clearness
         */
        /** @todo log the modification here */
        DAOFactory.getPostDAO().update(postID, // primary key
                             logonMemberName, postTopic, postBody,
                             now/*postLastEditDate*/, postLastEditIP, postFormatOption,
                             postOption, postStatus, postIcon);
        DAOFactory.getPostDAO().increaseEditCount(postID);

        if (postBean.getParentPostID() == 0) {//edit a top post ( thread )
            String threadIcon = postIcon;
            DAOFactory.getThreadDAO().updateTopic_Body_Icon(threadID, postTopic, postBody, threadIcon);
        }

        boolean attachMore  = ParamUtil.getParameterBoolean(request, "AttachMore");
        boolean addFavoriteThread = ParamUtil.getParameterBoolean(request, "AddFavoriteParentThread");
        boolean addWatchThread    = ParamUtil.getParameterBoolean(request, "AddWatchParentThread");
        //add favorite thread if user checked it
        if (addFavoriteThread) {
            permission.ensureIsAuthenticated();
            //@todo: add checking of MVNForumConfig.getEnableFavoriteThread()
            // check to make sure that this user doesnt exceed his favorite max
            int currentFavoriteCount = DAOFactory.getFavoriteThreadDAO().getNumberOfFavoriteThreads_inMember(logonMemberID);
            int maxFavorites = MVNForumConfig.getMaxFavoriteThread();
            if (currentFavoriteCount < maxFavorites) {
                Timestamp favoriteCreationDate = now;
                int favoriteType = 0; //@todo implement it later
                int favoriteOption = 0; //@todo implement it later
                int favoriteStatus = 0; //@todo implement it later

                // now check permission the this user have the readPost permission
                permission.ensureCanReadPost(forumID);

                // has the permission now, then insert to database
                try {
                    DAOFactory.getFavoriteThreadDAO().create(logonMemberID, threadID, forumID,
                        favoriteCreationDate, favoriteType, favoriteOption, favoriteStatus);
                } catch (DuplicateKeyException ex) {
                    // already add favorite thread, just ignore
                }
            }
        }

        //add watch if user checked it
        if (addWatchThread) {
            permission.ensureIsAuthenticated();
            permission.ensureIsActivated();
            if (MVNForumConfig.getEnableWatch() == false) {
                // should never happen, because if it happen, then the whole process is broken
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_add_watch.watch_is_disabled");
                throw new AssertionException(localizedMessage);
                //throw new AssertionException("Cannot add Watch because Watch feature is disabled by administrator.");
            }

            int watchType               = 0;//ParamUtil.getParameterInt(request, "WatchType");
            int watchOption             = 0;//ParamUtil.getParameterInt(request, "WatchOption");
            int watchStatus             = 0;//ParamUtil.getParameterInt(request, "WatchStatus");
            Timestamp watchCreationDate = now;
            Timestamp watchLastSentDate = now;
            Timestamp watchEndDate      = now;// @todo: check it !!!

            try {
                DAOFactory.getWatchDAO().create(logonMemberID, 0/*watchCategoryID*/, 0/*watchForumID*/,
                                           threadID, watchType, watchOption,
                                           watchStatus, watchCreationDate, watchLastSentDate,
                                           watchEndDate);
            } catch (DuplicateKeyException ex) {
                // User try to create a duplicate watch, just ignore
            }
        }

        request.setAttribute("ForumID", String.valueOf(forumID));
        request.setAttribute("ThreadID", String.valueOf(threadID));
        request.setAttribute("AttachMore", new Boolean(attachMore));
        request.setAttribute("PostBean", postBean);

        // now update the search index
        //@todo : modify for better performance here
        PostIndexer.scheduleUpdatePostTask(DAOFactory.getPostDAO().getPost(postID));
    }

    void prepareDelete(HttpServletRequest request)
        throws ObjectNotFoundException, BadInputException, DatabaseException, AuthenticationException, AssertionException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        // user must have been authenticated before he can delete
        permission.ensureIsAuthenticated();
        Locale locale = I18nUtil.getLocaleInRequest(request);

        // primary key column(s)
        int postID = ParamUtil.getParameterInt(request, "post");

        PostBean postBean = null;
        try {
            postBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int forumID = postBean.getForumID();

        try {
            ForumCache.getInstance().getBean(forumID).ensureNotDisabledForum();
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }


        if (postBean.getParentPostID() == 0) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_root_post");
            throw new BadInputException(localizedMessage);
            //throw new BadInputException("Cannot delete a root post. Use delete thread instead.");
        }

        // check constraint
        int logonMemberID   = onlineUser.getMemberID();
        int authorID        = postBean.getMemberID();
        if (permission.canDeletePost(forumID)) {
            // have permission, just do nothing, that is dont check the max day contraint
        } else if (logonMemberID == authorID) {// same author
            // check date here, usually must not older than 7 days
            Timestamp now = DateUtil.getCurrentGMTTimestamp();
            Timestamp postDate = postBean.getPostCreationDate();
            int maxDays = MVNForumConfig.getMaxDeleteDays();
            if ( (now.getTime() - postDate.getTime()) > (DateUtil.DAY * maxDays) ) {
                /** @todo choose a better Exception here */
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete.post_is_too_old");
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("You cannot delete a post which is older than " + maxDays + " days.");
            }

            //Check to make sure that "no reply" for this post
            int threadID = postBean.getThreadID();
            Collection postBeans = DAOFactory.getPostDAO().getEnablePosts_inThread_limit(threadID, 0, 10000);
            boolean foundReply = false;
            for (Iterator ite = postBeans.iterator(); ite.hasNext(); ) {
                PostBean tPostBean = (PostBean) ite.next();
                if (tPostBean.getParentPostID() == postBean.getPostID()) {
                    foundReply = true;
                    break;
                }
            }
            if (foundReply) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_post.post_has_reply");
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("Cannot delete a post that has reply!");
            }

            if (postBean.getPostStatus() == PostBean.POST_STATUS_DISABLED) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_your_own_post.post_is_in_pending_status");
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("Cannot delete your own post in pending status.");
            }
        } else {//not an author, so this user must have Edit Permission
            permission.ensureCanDeletePost(forumID);// this method ALWAYS throws AuthenticationException
        }

        request.setAttribute("PostBean", postBean);
    }

    void processDelete(HttpServletRequest request)
        throws BadInputException, DatabaseException, AuthenticationException, AssertionException, ObjectNotFoundException {

        Locale locale = I18nUtil.getLocaleInRequest(request);

        // primary key column(s)
        int postID = ParamUtil.getParameterInt(request, "post");
        PostBean postBean = null;
        try {
            postBean = DAOFactory.getPostDAO().getPost(postID);
        } catch(ObjectNotFoundException ex) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        // now check the password
        MyUtil.ensureCorrectCurrentPassword(request);

        ForumCache.getInstance().getBean(postBean.getForumID()).ensureNotDisabledForum();

        // delete the post and children attachments
        deletePost(request, postBean);

        int threadID = postBean.getThreadID();
        int forumID = postBean.getForumID();


        // now update the forum and thread statistics
        StatisticsUtil.updateForumStatistics(forumID);
        StatisticsUtil.updateThreadStatistics(threadID);

        request.setAttribute("ForumID", String.valueOf(forumID));
        request.setAttribute("ThreadID", String.valueOf(threadID));
    }

    // Note that this method does not update the forum statistics and thread statistics
    private void deletePost(HttpServletRequest request, PostBean postBean)
        throws AssertionException, DatabaseException, AuthenticationException,
        BadInputException, ObjectNotFoundException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        // user must have been authenticated before he can delete
        permission.ensureIsAuthenticated();

        int parentPostID = postBean.getParentPostID();

        Locale locale = I18nUtil.getLocaleInRequest(request);

        if (parentPostID == 0) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_root_post");
            throw new BadInputException(localizedMessage);
            //throw new BadInputException("Cannot delete a root post. Use delete thread instead.");
        }

        int forumID = postBean.getForumID();

        // check constraint
        int logonMemberID   = onlineUser.getMemberID();
        int authorID        = postBean.getMemberID();
        if (permission.canDeletePost(forumID)) {
            // have permission, just do nothing, that is dont check the max day contraint
        } else if (logonMemberID == authorID) {// same author
            // check date here, usually must not older than 7 days
            Timestamp now = DateUtil.getCurrentGMTTimestamp();
            Timestamp postDate = postBean.getPostCreationDate();
            int maxDays = MVNForumConfig.getMaxDeleteDays();
            if ( (now.getTime() - postDate.getTime()) > (DateUtil.DAY * maxDays) ) {
                /** @todo choose a better Exception here */
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete.post_is_too_old", new Object[] {new Integer(maxDays)});
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("You cannot delete a post which is older than " + maxDays + " days.");
            }

            //Check to make sure that "no reply" for this post
            int threadID = postBean.getThreadID();
            Collection postBeans = DAOFactory.getPostDAO().getEnablePosts_inThread_limit(threadID, 0, 10000);
            boolean foundReply = false;
            for (Iterator ite = postBeans.iterator(); ite.hasNext(); ) {
                PostBean tPostBean = (PostBean) ite.next();
                if (tPostBean.getParentPostID() == postBean.getPostID()) {
                    foundReply = true;
                    break;
                }
            }
            if (foundReply) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_post.post_has_reply");
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("Cannot delete a post that has reply!");
            }

            if (postBean.getPostStatus() == PostBean.POST_STATUS_DISABLED) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_delete_your_own_post.post_is_in_pending_status");
                throw new BadInputException(localizedMessage);
                //throw new BadInputException("Cannot delete your own disabled post.");
            }
        } else {//not an author, so this user must have Edit Permission
            permission.ensureCanDeletePost(forumID);// this method ALWAYS throws AuthenticationException
        }

        int postID = postBean.getPostID();

        // Delete all attachments in this post,
        // we must call this before any attempt to delete the post
        AttachmentWebHandler.deleteAttachments_inPost(postID);

        // now delete the post, note that we delete it after delete all child objects (attachment)
        DAOFactory.getPostDAO().delete(postID);

        try {
            DAOFactory.getPostDAO().updateParentPostID(postID, parentPostID);
        } catch (ObjectNotFoundException ex) {
            // we just ignore if no post is affect by this method
        }

        int memberID = postBean.getMemberID();
        StatisticsUtil.updateMemberStatistics(memberID);

        // now update the search index
        PostIndexer.scheduleDeletePostTask(postID, DeletePostIndexTask.OBJECT_TYPE_POST);
    }

    void prepareModeratePendingPosts_limit(HttpServletRequest request)
        throws AssertionException, DatabaseException, AuthenticationException, BadInputException,
        DatabaseException, ObjectNotFoundException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        Locale locale = I18nUtil.getLocaleInRequest(request);

        int threadID = ParamUtil.getParameterInt(request, "thread");
        ThreadBean threadBean = null;
        try {
            threadBean = DAOFactory.getThreadDAO().getThread(threadID);
        } catch ( ObjectNotFoundException ex ) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int forumID = threadBean.getForumID();

        try {
            ForumCache.getInstance().getBean(forumID).ensureNotDisabledForum();
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        int numberOfPosts = DAOFactory.getPostDAO().getNumberOfDisablePosts_inThread(threadID);

        // user must have been authenticated before he can view pending/disabled threads
        permission.ensureIsAuthenticated();

        // check normal permission
        permission.ensureCanModerateThread(forumID);

        int postsPerPage = 10000;
        int offset = 0;

        Collection postBeans = DAOFactory.getPostDAO().getDisablePosts_inThread_limit(threadID, offset, postsPerPage);

        Iterator iterator = postBeans.iterator();
        while (iterator.hasNext()) {
            PostBean postBean = (PostBean) iterator.next();
            // very slow here
            /** @todo find a better solution */
            MemberBean memberBean = null;
            if (postBean.getMemberID() != 0 && postBean.getMemberID() != MVNForumConstant.MEMBER_ID_OF_GUEST) {
                memberBean = DAOFactory.getMemberDAO().getMember_forPublic(postBean.getMemberID());
            }
            postBean.setMemberBean(memberBean);

            int postAttachCount = postBean.getPostAttachCount();
            if ((postAttachCount > 0) && MVNForumConfig.getEnableAttachment()) {
                int postID = postBean.getPostID();
                Collection attachBeans = DAOFactory.getAttachmentDAO().getAttachments_inPost(postID);
                int actualAttachCount = attachBeans.size();

                // now check if the attachCount in talbe Post equals to the actual attachCount in table Attachment
                if (postAttachCount != actualAttachCount) {
                    if (actualAttachCount != DAOFactory.getAttachmentDAO().getNumberOfAttachments_inPost(postID)) {
                        String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.serious_error.cannot_process_attachment_count");
                        throw new AssertionException(localizedMessage);
                        //throw new AssertionException("AssertionException: Serious error: cannot process Attachment Count in table Attachment");
                    }
                    log.warn("The attachment count in table Post and Attachment are not synchronized. In table Post = " +
                            postAttachCount + " and in table Attachment = " + actualAttachCount + ". Synchronize to " + actualAttachCount);
                    DAOFactory.getPostDAO().updateAttachCount(postID, actualAttachCount);
                }
                if (actualAttachCount > 0) {
                    postBean.setAttachmentBeans(attachBeans);
                }
            }
        }

        PostBean firstPostBean = DAOFactory.getPostDAO().getFirstPost_inThread(threadID);
        if (firstPostBean.getMemberID() != 0 && firstPostBean.getMemberID() != MVNForumConstant.MEMBER_ID_OF_GUEST) {
            MemberBean memberBean = DAOFactory.getMemberDAO().getMember_forPublic(firstPostBean.getMemberID());
            firstPostBean.setMemberBean(memberBean);
        }


        request.setAttribute("ThreadBean", threadBean);
        request.setAttribute("FirstPostBean", firstPostBean);
        request.setAttribute("PostBeans", postBeans);
        request.setAttribute("NumberOfPosts", new Integer(numberOfPosts));
    }

    void processModeratePendingPosts(HttpServletRequest request)
        throws AssertionException, DatabaseException, AuthenticationException,
        BadInputException, DatabaseException, ObjectNotFoundException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();
        Locale locale = I18nUtil.getLocaleInRequest(request);

        // user must have been authenticated before he can moderate pending/disabled posts
        permission.ensureIsAuthenticated();

        // check normal permission, note that we dont check
        // permission on a forumID because we allow moderate posts
        // in multiple forums even if the web interface does not support it
        int threadID = -1;
        int forumID = -1;
        try {
            threadID = ParamUtil.getParameterInt(request, "thread");
            ThreadBean threadBean = null;
            try {
                threadBean = DAOFactory.getThreadDAO().getThread(threadID);
            } catch ( ObjectNotFoundException ex ) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
                throw new ObjectNotFoundException(localizedMessage);
            }
            forumID = threadBean.getForumID();
            permission.ensureCanModerateThread(forumID);
            ForumCache.getInstance().getBean(forumID).ensureNotDisabledForum();
        } catch (BadInputException ex) {
            // just ignore, in case of use customized client
        }
        permission.ensureCanModerateThreadInAnyForum();

        try {
            String prefix = "modpostaction_";
            for (Enumeration enumeration = request.getParameterNames(); enumeration.hasMoreElements(); ) {
                String param = (String) enumeration.nextElement();
                if (param.startsWith(prefix)) {
                    String modValue = ParamUtil.getParameter(request, param, true);
                    String strPostID = param.substring(prefix.length());
                    int postID = Integer.parseInt(strPostID);
                    if (modValue.equals("approve")) {
                        PostBean postBean = null;
                        try {
                            postBean = DAOFactory.getPostDAO().getPost(postID);
                        } catch(ObjectNotFoundException ex) {
                            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
                            throw new ObjectNotFoundException(localizedMessage);
                        }
                        int currentForumID = postBean.getForumID();
                        permission.ensureCanModerateThread(currentForumID);
                        DAOFactory.getPostDAO().updateStatus(postID, PostBean.POST_STATUS_DEFAULT);
                    } else if (modValue.equals("delete")) {
                        PostBean postBean = null;
                        try {
                            postBean = DAOFactory.getPostDAO().getPost(postID);
                        } catch(ObjectNotFoundException ex) {
                            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.postid_not_exists", new Object[] {new Integer(postID)});
                            throw new ObjectNotFoundException(localizedMessage);
                        }
                        deletePost(request, postBean);
                    } else {
                        // it means ignore, do nothing
                    }
                }
            }
        } finally {
            // now update the forum statistics
            if (forumID != -1) {
                StatisticsUtil.updateForumStatistics(forumID);
            }

            // now update the thread statistics
            if (threadID != -1) {
                StatisticsUtil.updateThreadStatistics(threadID);
            }
        }

        request.setAttribute("ForumID", String.valueOf(forumID));
        request.setAttribute("ThreadID", String.valueOf(threadID));
    }

    /**
     * This method is for viewthread page and printthread page
     */
    void prepareViewThread(HttpServletRequest request)
        throws DatabaseException, ObjectNotFoundException, BadInputException, AuthenticationException, AssertionException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        Locale locale = I18nUtil.getLocaleInRequest(request);

        int threadID = ParamUtil.getParameterInt(request, "thread");
        boolean printAll = ParamUtil.getParameterBoolean(request, "printall");
        ThreadBean threadBean = null;
        try {
            threadBean = DAOFactory.getThreadDAO().getThread(threadID);
        } catch ( ObjectNotFoundException ex ) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
            throw new ObjectNotFoundException(localizedMessage);
        }
        int forumID = threadBean.getForumID();
        int numberOfPosts = DAOFactory.getPostDAO().getNumberOfEnablePosts_inThread(threadID);

        // check normal permission
        permission.ensureCanReadPost(forumID);

        //ForumBean forumBean = null;
        try {
            ForumCache.getInstance().getBean(forumID).ensureNotDisabledForum();
        } catch (ObjectNotFoundException e) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.forumid_not_exists", new Object[] {new Integer(forumID)});
            throw new ObjectNotFoundException(localizedMessage);
        }

        // Only moderator can view disable threads
        if (threadBean.getThreadStatus() == ThreadBean.THREAD_STATUS_DISABLED) {
            permission.ensureCanModerateThread(forumID);
        }

        int postsPerPage = onlineUser.getPostsPerPage();
        int offset = 0;
        boolean lastPage = ParamUtil.getParameterBoolean(request, "lastpage");
        if (lastPage) {
            // note that in the worst case, numberOfPosts could equals 0 (bad database)
            int pageCount = numberOfPosts / postsPerPage;
            int odd = numberOfPosts % postsPerPage;
            if (odd > 0) {
                pageCount++;
            }
            if (pageCount < 1) {
                pageCount = 1;// at least, there is one page
            }
            offset = (pageCount-1) * postsPerPage;
        } else {
            try {
                offset = ParamUtil.getParameterInt(request, "offset");
            } catch (BadInputException e) {
                // do nothing
            }
        }
        if (printAll) {
            postsPerPage = 10000; //We assume that big number
            offset = 0;
        }

        Collection postBeans = DAOFactory.getPostDAO().getEnablePosts_inThread_limit(threadID, offset, postsPerPage);

        Iterator iterator = postBeans.iterator();
        while(iterator.hasNext()) {
            PostBean postBean = (PostBean)iterator.next();
            // very slow here
            /** @todo find a better solution */
            MemberBean memberBean = null;
            if (postBean.getMemberID() != 0 && postBean.getMemberID() != MVNForumConstant.MEMBER_ID_OF_GUEST) {
                memberBean = DAOFactory.getMemberDAO().getMember_forPublic(postBean.getMemberID());
            }
            postBean.setMemberBean(memberBean);

            int postAttachCount = postBean.getPostAttachCount();
            if ( (postAttachCount > 0) && MVNForumConfig.getEnableAttachment()) {
                int postID = postBean.getPostID();
                Collection attachBeans = DAOFactory.getAttachmentDAO().getAttachments_inPost(postID);
                int actualAttachCount = attachBeans.size();

                // now check if the attachCount in talbe Post equals to the actual attachCount in table Attachment
                if (postAttachCount != actualAttachCount) {
                    if (actualAttachCount != DAOFactory.getAttachmentDAO().getNumberOfAttachments_inPost(postID)) {
                        String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.serious_error.cannot_process_attachment_count");
                        throw new AssertionException(localizedMessage);
                        //throw new AssertionException("AssertionException: Serious error: cannot process Attachment Count in table Attachment");
                    }
                    log.warn("The attachment count in table Post and Attachment are not synchronized. In table Post = " + postAttachCount + " and in table Attachment = " + actualAttachCount + ". Synchronize to " + actualAttachCount);
                    DAOFactory.getPostDAO().updateAttachCount(postID, actualAttachCount);
                }
                if (actualAttachCount > 0) {
                    postBean.setAttachmentBeans(attachBeans);
                }
            }
        }

        int previousTopic = DAOFactory.getThreadDAO().getPreviousEnableThread(forumID, threadID);// can throw AssertionException
        int nextTopic     = DAOFactory.getThreadDAO().getNextEnableThread(forumID, threadID);// can throw AssertionException

        int pendingPostCount = 0;
        if (permission.canModerateThread(forumID)) {
            pendingPostCount = DAOFactory.getPostDAO().getNumberOfDisablePosts_inThread(threadID);
        }

        DAOFactory.getThreadDAO().increaseViewCount(threadID);

        request.setAttribute("ThreadBean", threadBean);
        request.setAttribute("PostBeans", postBeans);
        request.setAttribute("NumberOfPosts", new Integer(numberOfPosts));
        request.setAttribute("PreviousTopic", new Integer(previousTopic));
        request.setAttribute("NextTopic", new Integer(nextTopic));
        request.setAttribute("PendingPostCount", new Integer(pendingPostCount));
    }

    void prepareSearch(HttpServletRequest request)
        throws AssertionException {

        if (!MVNForumConfig.getEnableSearch()) {
            Locale locale = I18nUtil.getLocaleInRequest(request);
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.search_disabled");
            throw new AssertionException(localizedMessage);
        }
    }

    void processSearch(HttpServletRequest request, HttpServletResponse response)
        throws BadInputException, IOException, DatabaseException,
        ObjectNotFoundException, AuthenticationException, AssertionException {

        OnlineUser onlineUser = onlineUserManager.getOnlineUser(request);
        MVNForumPermission permission = onlineUser.getPermission();

        Locale locale = I18nUtil.getLocaleInRequest(request);

        if (!MVNForumConfig.getEnableSearch()) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.search_disabled");
            throw new AssertionException(localizedMessage);
        }

        MyUtil.saveVNTyperMode(request, response);

        String memberName = ParamUtil.getParameter(request, "member");
        StringUtil.checkGoodName(memberName);

        int minAttachmentCount = ParamUtil.getParameterInt(request, "minattach", 0);

        // if user does not enter MemberName or attachment, then user must enter "key"
        boolean requireKey = ((memberName.length() == 0) && (minAttachmentCount == 0));
        String key  = ParamUtil.getParameter(request, "key", requireKey);

        int forumID = ParamUtil.getParameterInt(request, "forum", 0);//negative means category
        int offset  = ParamUtil.getParameterUnsignedInt(request, "offset", 0);
        int rows    = ParamUtil.getParameterUnsignedInt(request, "rows", 20);
        if (rows == 0) {
            rows = 20;// fix NullPointerException when rows = 0
        }

        // offset should be even when divide with rowsToReturn
        offset = (offset / rows) * rows;

        PostSearchQuery query = new PostSearchQuery();

        if (key.length() > 0) {
            query.setSearchString(key);
            int scopeInPost = ParamUtil.getParameterInt(request, "scopeinpost", PostSearchQuery.SEARCH_ONLY_BODY|PostSearchQuery.SEARCH_ONLY_TITLE);
            query.setScopeInPost(scopeInPost);
        }

        if (memberName.length() > 0) {
            try {
                int memberID = DAOFactory.getMemberDAO().getMemberIDFromMemberName(memberName);
                query.setMemberId(memberID);
            } catch(ObjectNotFoundException ex) {
                String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.membername_not_exists", new Object[] {memberName});
                throw new ObjectNotFoundException(localizedMessage);
            }
        }

        if (minAttachmentCount > 0) {
            query.setMinAttachmentCount(minAttachmentCount);
        }

        int searchDate        = ParamUtil.getParameterUnsignedInt(request, "date", PostSearchQuery.SEARCH_ANY_DATE);
        int searchBeforeAfter = ParamUtil.getParameterInt(request, "beforeafter", PostSearchQuery.SEARCH_NEWER);

        if ((searchDate != PostSearchQuery.SEARCH_ANY_DATE) && (searchDate < 365 * 10)) { // 10 years
            long deltaTime = DateUtil.DAY * searchDate;

            Timestamp now = DateUtil.getCurrentGMTTimestamp();
            Timestamp from = null;
            Timestamp to = null;

            long currentTime = now.getTime();

            if (searchBeforeAfter == PostSearchQuery.SEARCH_NEWER) {
                from = new Timestamp(currentTime - deltaTime);
            } else {// older
                to = new Timestamp(currentTime - deltaTime);
            }

            query.setFromDate(from);
            query.setToDate(to);
        }

        if (forumID > 0) {
            query.setForumId(forumID);
        } else if (forumID < 0) {
            // choose to search in a category
            query.setForumId(forumID);
        } else {
            // forumID equals to 0, it mean global searching
            // just do nothing, lucene will search all forums (globally)
        }

        query.searchDocuments(offset, rows, permission);
        int hitCount = query.getHitCount();
        Collection result = query.getPostResult();

        // Remove postd that current user dont have permission
        // NOTE: these below code does not remove the enable posts in
        // a disabled thread. This is not usually the case because
        // normally we will delete the thread instead of change it
        // from Enable to Disabled
        for (Iterator iter = result.iterator(); iter.hasNext(); ) {
            PostBean postBean = (PostBean)iter.next();
            int currentForumID = postBean.getForumID();
            if (ForumCache.getInstance().getBean(currentForumID).getForumStatus() == ForumBean.FORUM_STATUS_DISABLED) {
                iter.remove();
            } else if ( (permission.canReadPost(currentForumID) == false) ||
                 (postBean.getPostStatus() == PostBean.POST_STATUS_DISABLED)) {
                iter.remove();
            }
            else if (postBean.getParentPostID() == 0) {// first post
                // Please note that the first post is always Enable even if
                // the thread is Disable. In this case always show result
                // if the current user is moderator
                if (permission.canModerateThread(currentForumID) == false) {
                    int threadID = postBean.getThreadID();
                    ThreadBean threadBean = null;
                    try {
                        threadBean = DAOFactory.getThreadDAO().getThread(threadID);
                    } catch ( ObjectNotFoundException ex ) {
                        String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.threadid_not_exists", new Object[] {new Integer(threadID)});
                        throw new ObjectNotFoundException(localizedMessage);
                    }
                    if (threadBean.getThreadStatus() == ThreadBean.THREAD_STATUS_DISABLED) {
                        iter.remove();
                    }
                }
            }
        }

        if (offset > hitCount) {
            String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.offset_greater_than_total_rows");
            throw new BadInputException(localizedMessage);
            //throw new BadInputException("Cannot search with offset > total posts");
        }

//        request.setAttribute("key", Encoder.encodeURL(key));
//        request.setAttribute("member", memberName);
//        request.setAttribute("forum", new Integer(forumID));
//        request.setAttribute("offset", new Integer(offset));
//        request.setAttribute("attachment", new Boolean(withAttachment));
        request.setAttribute("rows", new Integer(rows));
        request.setAttribute("TotalPosts", new Integer(hitCount));
        request.setAttribute("PostBeans", result);
        request.setAttribute("SearchQuery", query);
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.