org.jamwiki.servlets.EditServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.jamwiki.servlets.EditServlet.java

Source

/**
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the latest version of the GNU Lesser General
 * Public License as published by the Free Software Foundation;
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program (LICENSE.txt); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.jamwiki.servlets;

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

import org.apache.commons.lang.StringUtils;
import org.jamwiki.WikiBase;
import org.jamwiki.WikiException;
import org.jamwiki.WikiMessage;
import org.jamwiki.authentication.RoleImpl;
import org.jamwiki.authentication.WikiUserDetails;
import org.jamwiki.model.Topic;
import org.jamwiki.model.TopicVersion;
import org.jamwiki.model.WikiUser;
import org.jamwiki.parser.ParserInput;
import org.jamwiki.parser.ParserOutput;
import org.jamwiki.parser.ParserUtil;
import org.jamwiki.utils.LinkUtil;
import org.jamwiki.utils.NamespaceHandler;
import org.jamwiki.utils.WikiLink;
import org.jamwiki.utils.WikiLogger;
import org.jamwiki.utils.WikiUtil;
import org.springframework.web.servlet.ModelAndView;

/**
 * Used to process topic edits including saving an edit, preview, resolving
 * conflicts and dealing with spam.
 */
public class EditServlet extends JAMWikiServlet {

    private static final WikiLogger logger = WikiLogger.getLogger(EditServlet.class.getName());
    /** The name of the JSP file used to render the servlet output. */
    protected static final String JSP_EDIT = "edit.jsp";

    /**
      *
      */
    protected ModelAndView handleJAMWikiRequest(HttpServletRequest request, HttpServletResponse response,
            ModelAndView next, WikiPageInfo pageInfo) throws Exception {
        ModelAndView loginRequired = loginRequired(request, pageInfo);
        if (loginRequired != null) {
            return loginRequired;
        }
        if (isSave(request)) {
            save(request, next, pageInfo);
        } else {
            edit(request, next, pageInfo);
        }
        return next;
    }

    /**
      *
      */
    private void edit(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo) throws Exception {
        String topicName = WikiUtil.getTopicFromRequest(request);
        String virtualWiki = pageInfo.getVirtualWikiName();
        Topic topic = loadTopic(virtualWiki, topicName);
        // topic name might be updated by loadTopic
        topicName = topic.getName();
        // Integer lastTopicVersionId = retrieveLastTopicVersionId(request, topic);
        // next.addObject("lastTopicVersionId", lastTopicVersionId);
        String contents = (String) request.getParameter("contents");
        if (isPreview(request)) {
            preview(request, next, pageInfo);
        } else if (isShowChanges(request)) {
            // showChanges(request, next, pageInfo, virtualWiki, topicName,
            // lastTopicVersionId);
            // } else if
            // (!StringUtils.isBlank(request.getParameter("topicVersionId"))) {
            // // editing an older version
            // Integer topicVersionId =
            // Integer.valueOf(request.getParameter("topicVersionId"));
            // TopicVersion topicVersion =
            // WikiBase.getDataHandler().lookupTopicVersion(topicVersionId);
            // if (topicVersion == null) {
            // throw new WikiException(new WikiMessage("common.exception.notopic"));
            // }
            // contents = topicVersion.getVersionContent();
            // if (!lastTopicVersionId.equals(topicVersionId)) {
            // next.addObject("topicVersionId", topicVersionId);
            // }
        } else if (!StringUtils.isBlank(request.getParameter("section"))) {
            // editing a section of a topic
            int section = Integer.valueOf(request.getParameter("section"));
            String[] sliceResults = ParserUtil.parseSlice(request.getContextPath(), request.getLocale(),
                    virtualWiki, topicName, section);
            contents = sliceResults[1];
            String sectionName = sliceResults[0];
            String editComment = "/* " + sectionName + " */ ";
            next.addObject("editComment", editComment);
        } else {
            // editing a full new or existing topic
            contents = (topic == null) ? "" : topic.getTopicContent();
        }
        this.loadEdit(request, next, pageInfo, contents, virtualWiki, topicName, true);
    }

    /**
      *
      */
    private boolean isPreview(HttpServletRequest request) {
        return !StringUtils.isBlank(request.getParameter("preview"));
    }

    /**
      *
      */
    private boolean isSave(HttpServletRequest request) {
        return !StringUtils.isBlank(request.getParameter("save"));
    }

    /**
      *
      */
    private boolean isShowChanges(HttpServletRequest request) {
        return !StringUtils.isBlank(request.getParameter("showChanges"));
    }

    /**
      *
      */
    private void loadDiff(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo, String contents1,
            String contents2) throws Exception {
        // List<WikiDiff> diffs = DiffUtil.diff(contents1, contents2);
        // next.addObject("diffs", diffs);
    }

    /**
      *
      */
    private void loadEdit(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo, String contents,
            String virtualWiki, String topicName, boolean useSection) throws Exception {
        pageInfo.setPageTitle(new WikiMessage("edit.title", topicName));
        pageInfo.setTopicName(topicName);
        WikiLink wikiLink = LinkUtil.parseWikiLink(topicName);
        String namespace = wikiLink.getNamespace();
        if (namespace != null && namespace.equals(NamespaceHandler.NAMESPACE_CATEGORY)) {
            ServletUtil.loadCategoryContent(next, virtualWiki, topicName);
        }
        if (request.getParameter("editComment") != null) {
            next.addObject("editComment", request.getParameter("editComment"));
        }
        if (useSection && request.getParameter("section") != null) {
            next.addObject("section", request.getParameter("section"));
        }
        next.addObject("minorEdit", (request.getParameter("minorEdit") != null));
        // Watchlist watchlist = ServletUtil.currentWatchlist(request, virtualWiki);
        // if (request.getParameter("watchTopic") != null ||
        // (watchlist.containsTopic(topicName) && !isPreview(request))) {
        // next.addObject("watchTopic", true);
        // }
        pageInfo.setContentJsp(JSP_EDIT);
        WikiUser user = ServletUtil.currentWikiUser();
        String editor = user.getEditor();
        next.addObject("editor", editor);
        next.addObject("contents", contents);
    }

    /**
     * Initialize topic values for the topic being edited. If a topic with the
     * specified name already exists then it will be initialized, otherwise a new
     * topic is created.
     */
    private Topic loadTopic(String virtualWiki, String topicName) throws Exception {
        Topic topic = ServletUtil.initializeTopic(virtualWiki, topicName);
        // if (topic.getReadOnly()) {
        // throw new WikiException(new WikiMessage("error.readonly"));
        // }
        return topic;
    }

    /**
      *
      */
    private ModelAndView loginRequired(HttpServletRequest request, WikiPageInfo pageInfo) throws Exception {
        String topicName = WikiUtil.getTopicFromRequest(request);
        String virtualWiki = pageInfo.getVirtualWikiName();
        WikiUserDetails user = ServletUtil.currentUserDetails();
        if (ServletUtil.isEditable(virtualWiki, topicName, user)) {
            return null;
        }
        if (!user.hasRole(RoleImpl.ROLE_EDIT_EXISTING)) {
            WikiMessage messageObject = new WikiMessage("login.message.edit");
            return ServletUtil.viewLogin(request, pageInfo, WikiUtil.getTopicFromURI(request), messageObject);
        }
        if (!user.hasRole(RoleImpl.ROLE_EDIT_NEW)
                && WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null) == null) {
            WikiMessage messageObject = new WikiMessage("login.message.editnew");
            return ServletUtil.viewLogin(request, pageInfo, WikiUtil.getTopicFromURI(request), messageObject);
        }
        Topic topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
        if (topic == null) {
            // this should never trigger, but better safe than sorry...
            return null;
        }
        // if (topic.getAdminOnly()) {
        // WikiMessage messageObject = new WikiMessage("login.message.editadmin",
        // topicName);
        // return ServletUtil.viewLogin(request, pageInfo,
        // WikiUtil.getTopicFromURI(request), messageObject);
        // }
        // if (topic.getReadOnly()) {
        // throw new WikiException(new WikiMessage("error.readonly"));
        // }
        // it should be impossible to get here...
        throw new WikiException(new WikiMessage("error.unknown", "Unable to determine topic editing permissions"));
    }

    /**
     * Functionality to handle the "Preview" button being clicked.
     */
    private void preview(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo) throws Exception {
        String topicName = WikiUtil.getTopicFromRequest(request);
        String virtualWiki = pageInfo.getVirtualWikiName();
        String contents = (String) request.getParameter("contents");
        Topic previewTopic = new Topic();
        previewTopic.setName(topicName);
        previewTopic.setTopicContent(contents);
        previewTopic.setVirtualWiki(virtualWiki);
        next.addObject("editPreview", "true");
        ServletUtil.viewTopic(request, next, pageInfo, null, previewTopic, false, false);
    }

    /**
      *
      */
    private void resolve(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo) throws Exception {
        String topicName = WikiUtil.getTopicFromRequest(request);
        String virtualWiki = pageInfo.getVirtualWikiName();
        Topic lastTopic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
        String contents1 = lastTopic.getTopicContent();
        String contents2 = request.getParameter("contents");
        // next.addObject("lastTopicVersionId", lastTopic.getCurrentVersionId());
        next.addObject("contentsResolve", contents2);
        this.loadDiff(request, next, pageInfo, contents1, contents2);
        this.loadEdit(request, next, pageInfo, contents1, virtualWiki, topicName, false);
        next.addObject("editResolve", "true");
    }

    /**
      *
      */
    private Long retrieveLastTopicVersionId(HttpServletRequest request, Topic topic) throws Exception {
        return (!StringUtils.isBlank(request.getParameter("lastTopicVersionId")))
                ? Long.valueOf(request.getParameter("lastTopicVersionId"))
                : topic.getCurrentVersionId();
    }

    /**
     * Functionality to handle the "Save" button being clicked.
     */
    private void save(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo) throws Exception {
        String topicName = WikiUtil.getTopicFromRequest(request);
        String virtualWiki = pageInfo.getVirtualWikiName();
        Topic topic = loadTopic(virtualWiki, topicName);
        Topic lastTopic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null);
        if (lastTopic != null
                && !lastTopic.getCurrentVersionId().equals(retrieveLastTopicVersionId(request, topic))) {
            // someone else has edited the topic more recently
            resolve(request, next, pageInfo);
            return;
        }
        String contents = request.getParameter("contents");
        String sectionName = "";
        if (!StringUtils.isBlank(request.getParameter("section"))) {
            // load section of topic
            int section = Integer.valueOf(request.getParameter("section"));
            ParserOutput parserOutput = new ParserOutput();
            String[] spliceResult = ParserUtil.parseSplice(parserOutput, request.getContextPath(),
                    request.getLocale(), virtualWiki, topicName, section, contents);
            contents = spliceResult[1];
            sectionName = parserOutput.getSectionName();
        }
        if (contents == null) {
            logger.warning("The topic " + topicName + " has no content");
            throw new WikiException(new WikiMessage("edit.exception.nocontent", topicName));
        }
        // strip line feeds
        contents = StringUtils.remove(contents, '\r');
        String lastTopicContent = (lastTopic != null) ? StringUtils.remove(lastTopic.getTopicContent(), '\r') : "";
        if (lastTopic != null && StringUtils.equals(lastTopicContent, contents)) {
            // topic hasn't changed. redirect to prevent user from refreshing and
            // re-submitting
            ServletUtil.redirect(next, virtualWiki, topic.getName());
            return;
        }
        if (handleSpam(request, next, topicName, contents)) {
            this.loadEdit(request, next, pageInfo, contents, virtualWiki, topicName, false);
            return;
        }
        // parse for signatures and other syntax that should not be saved in raw
        // form
        WikiUser user = ServletUtil.currentWikiUser();
        ParserInput parserInput = new ParserInput();
        parserInput.setContext(request.getContextPath());
        parserInput.setLocale(request.getLocale());
        parserInput.setWikiUser(user);
        parserInput.setTopicName(topicName);
        parserInput.setUserDisplay(ServletUtil.getIpAddress(request));
        parserInput.setVirtualWiki(virtualWiki);
        ParserOutput parserOutput = ParserUtil.parseMetadata(parserInput, contents);
        // parse signatures and other values that need to be updated prior to saving
        contents = ParserUtil.parseMinimal(parserInput, contents);
        topic.setTopicContent(contents);
        // if (!StringUtils.isBlank(parserOutput.getRedirect())) {
        // // set up a redirect
        // topic.setRedirectTo(parserOutput.getRedirect());
        // topic.setTopicType(Topic.TYPE_REDIRECT);
        // } else if (topic.getTopicType() == Topic.TYPE_REDIRECT) {
        // // no longer a redirect
        // topic.setRedirectTo(null);
        // topic.setTopicType(Topic.TYPE_ARTICLE);
        // }
        int charactersChanged = StringUtils.length(contents) - StringUtils.length(lastTopicContent);
        TopicVersion topicVersion = new TopicVersion(user, ServletUtil.getIpAddress(request),
                request.getParameter("editComment"), contents, charactersChanged);
        if (request.getParameter("minorEdit") != null) {
            topicVersion.setEditType(TopicVersion.EDIT_MINOR);
        }
        WikiBase.getDataHandler().writeTopic(topic, topicVersion, parserOutput.getCategories(),
                parserOutput.getLinks());
        // // update watchlist
        WikiUserDetails userDetails = ServletUtil.currentUserDetails();
        if (!userDetails.hasRole(RoleImpl.ROLE_ANONYMOUS)) {
            // Watchlist watchlist = ServletUtil.currentWatchlist(request,
            // virtualWiki);
            // boolean watchTopic = (request.getParameter("watchTopic") != null);
            // if (watchlist.containsTopic(topicName) != watchTopic) {
            // WikiBase.getDataHandler().writeWatchlistEntry(watchlist, virtualWiki,
            // topicName, user.getUserId());
            // }
        }
        // redirect to prevent user from refreshing and re-submitting
        String target = topic.getName();
        if (!StringUtils.isBlank(sectionName)) {
            target += "#" + sectionName;
        }
        ServletUtil.redirect(next, virtualWiki, target);
    }

    /**
     * Functionality to handle the "Show Changes" button being clicked.
     */
    private void showChanges(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo,
            String virtualWiki, String topicName, Long lastTopicVersionId) throws Exception {
        String contents1 = request.getParameter("contents");
        String contents2 = "";
        if (!StringUtils.isBlank(request.getParameter("section"))) {
            // editing a section of a topic
            int section = Integer.valueOf(request.getParameter("section"));
            String[] sliceResults = ParserUtil.parseSlice(request.getContextPath(), request.getLocale(),
                    virtualWiki, topicName, section);
            contents2 = sliceResults[1];
        } else if (lastTopicVersionId != null) {
            // get the full topic version
            TopicVersion lastTopicVersion = WikiBase.getDataHandler().lookupTopicVersion(lastTopicVersionId);
            contents2 = lastTopicVersion.getVersionContent();
        }
        this.loadDiff(request, next, pageInfo, contents1, contents2);
        next.addObject("editShowChanges", "true");
    }
}