001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.action;
016    
017    import com.liferay.portal.kernel.captcha.CaptchaMaxChallengesException;
018    import com.liferay.portal.kernel.captcha.CaptchaTextException;
019    import com.liferay.portal.kernel.captcha.CaptchaUtil;
020    import com.liferay.portal.kernel.sanitizer.SanitizerException;
021    import com.liferay.portal.kernel.servlet.SessionErrors;
022    import com.liferay.portal.kernel.upload.UploadPortletRequest;
023    import com.liferay.portal.kernel.util.Constants;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.ObjectValuePair;
026    import com.liferay.portal.kernel.util.ParamUtil;
027    import com.liferay.portal.kernel.util.StreamUtil;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.kernel.workflow.WorkflowConstants;
031    import com.liferay.portal.security.auth.PrincipalException;
032    import com.liferay.portal.security.permission.ActionKeys;
033    import com.liferay.portal.security.permission.PermissionChecker;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.service.ServiceContextFactory;
036    import com.liferay.portal.struts.PortletAction;
037    import com.liferay.portal.theme.ThemeDisplay;
038    import com.liferay.portal.util.PortalUtil;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portal.util.WebKeys;
041    import com.liferay.portlet.ActionResponseImpl;
042    import com.liferay.portlet.asset.AssetCategoryException;
043    import com.liferay.portlet.asset.AssetTagException;
044    import com.liferay.portlet.documentlibrary.FileExtensionException;
045    import com.liferay.portlet.documentlibrary.FileNameException;
046    import com.liferay.portlet.documentlibrary.FileSizeException;
047    import com.liferay.portlet.messageboards.LockedThreadException;
048    import com.liferay.portlet.messageboards.MessageBodyException;
049    import com.liferay.portlet.messageboards.MessageSubjectException;
050    import com.liferay.portlet.messageboards.NoSuchMessageException;
051    import com.liferay.portlet.messageboards.RequiredMessageException;
052    import com.liferay.portlet.messageboards.model.MBMessage;
053    import com.liferay.portlet.messageboards.model.MBMessageConstants;
054    import com.liferay.portlet.messageboards.service.MBMessageServiceUtil;
055    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
056    import com.liferay.portlet.messageboards.service.MBThreadServiceUtil;
057    import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
058    
059    import java.io.InputStream;
060    
061    import java.util.ArrayList;
062    import java.util.List;
063    
064    import javax.portlet.ActionRequest;
065    import javax.portlet.ActionResponse;
066    import javax.portlet.PortletConfig;
067    import javax.portlet.PortletPreferences;
068    import javax.portlet.PortletURL;
069    import javax.portlet.RenderRequest;
070    import javax.portlet.RenderResponse;
071    
072    import org.apache.struts.action.ActionForm;
073    import org.apache.struts.action.ActionForward;
074    import org.apache.struts.action.ActionMapping;
075    
076    /**
077     * @author Brian Wing Shun Chan
078     * @author Daniel Sanz
079     * @author Shuyang Zhou
080     */
081    public class EditMessageAction extends PortletAction {
082    
083            @Override
084            public void processAction(
085                            ActionMapping actionMapping, ActionForm actionForm,
086                            PortletConfig portletConfig, ActionRequest actionRequest,
087                            ActionResponse actionResponse)
088                    throws Exception {
089    
090                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
091    
092                    try {
093                            MBMessage message = null;
094    
095                            if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
096                                    message = updateMessage(actionRequest, actionResponse);
097                            }
098                            else if (cmd.equals(Constants.DELETE)) {
099                                    deleteMessage(actionRequest);
100                            }
101                            else if (cmd.equals(Constants.LOCK)) {
102                                    lockThreads(actionRequest);
103                            }
104                            else if (cmd.equals(Constants.SUBSCRIBE)) {
105                                    subscribeMessage(actionRequest);
106                            }
107                            else if (cmd.equals(Constants.UNLOCK)) {
108                                    unlockThreads(actionRequest);
109                            }
110                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
111                                    unsubscribeMessage(actionRequest);
112                            }
113    
114                            if (Validator.isNotNull(cmd)) {
115                                    String redirect = getRedirect(
116                                            actionRequest, actionResponse, message);
117    
118                                    sendRedirect(actionRequest, actionResponse, redirect);
119                            }
120                    }
121                    catch (Exception e) {
122                            if (e instanceof NoSuchMessageException ||
123                                    e instanceof PrincipalException ||
124                                    e instanceof RequiredMessageException) {
125    
126                                    SessionErrors.add(actionRequest, e.getClass());
127    
128                                    setForward(actionRequest, "portlet.message_boards.error");
129                            }
130                            else if (e instanceof CaptchaMaxChallengesException ||
131                                             e instanceof CaptchaTextException ||
132                                             e instanceof FileExtensionException ||
133                                             e instanceof FileNameException ||
134                                             e instanceof FileSizeException ||
135                                             e instanceof LockedThreadException ||
136                                             e instanceof MessageBodyException ||
137                                             e instanceof MessageSubjectException ||
138                                             e instanceof SanitizerException) {
139    
140                                    SessionErrors.add(actionRequest, e.getClass());
141                            }
142                            else if (e instanceof AssetCategoryException ||
143                                             e instanceof AssetTagException) {
144    
145                                    SessionErrors.add(actionRequest, e.getClass(), e);
146                            }
147                            else {
148                                    Throwable cause = e.getCause();
149    
150                                    if (cause instanceof SanitizerException) {
151                                            SessionErrors.add(actionRequest, SanitizerException.class);
152                                    }
153                                    else {
154                                            throw e;
155                                    }
156                            }
157                    }
158            }
159    
160            @Override
161            public ActionForward render(
162                            ActionMapping actionMapping, ActionForm actionForm,
163                            PortletConfig portletConfig, RenderRequest renderRequest,
164                            RenderResponse renderResponse)
165                    throws Exception {
166    
167                    try {
168                            ActionUtil.getMessage(renderRequest);
169                    }
170                    catch (Exception e) {
171                            if (e instanceof NoSuchMessageException ||
172                                    e instanceof PrincipalException) {
173    
174                                    SessionErrors.add(renderRequest, e.getClass());
175    
176                                    return actionMapping.findForward(
177                                            "portlet.message_boards.error");
178                            }
179                            else {
180                                    throw e;
181                            }
182                    }
183    
184                    return actionMapping.findForward(
185                            getForward(renderRequest, "portlet.message_boards.edit_message"));
186            }
187    
188            protected void deleteMessage(ActionRequest actionRequest) throws Exception {
189                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
190    
191                    MBMessageServiceUtil.deleteMessage(messageId);
192            }
193    
194            protected String getRedirect(
195                    ActionRequest actionRequest, ActionResponse actionResponse,
196                    MBMessage message) {
197    
198                    if (message == null) {
199                            String redirect = ParamUtil.getString(actionRequest, "redirect");
200    
201                            return redirect;
202                    }
203    
204                    int workflowAction = ParamUtil.getInteger(
205                            actionRequest, "workflowAction", WorkflowConstants.ACTION_PUBLISH);
206    
207                    if (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT) {
208                            return getSaveAndContinueRedirect(
209                                    actionRequest, actionResponse, message);
210                    }
211                    else if (message == null) {
212                            return ParamUtil.getString(actionRequest, "redirect");
213                    }
214    
215                    ActionResponseImpl actionResponseImpl =
216                            (ActionResponseImpl)actionResponse;
217    
218                    PortletURL portletURL = actionResponseImpl.createRenderURL();
219    
220                    portletURL.setParameter(
221                            "struts_action", "/message_boards/view_message");
222                    portletURL.setParameter(
223                            "messageId", String.valueOf(message.getMessageId()));
224    
225                    return portletURL.toString();
226            }
227    
228            protected String getSaveAndContinueRedirect(
229                    ActionRequest actionRequest, ActionResponse actionResponse,
230                    MBMessage message) {
231    
232                    String redirect = ParamUtil.getString(actionRequest, "redirect");
233    
234                    boolean preview = ParamUtil.getBoolean(actionRequest, "preview");
235    
236                    PortletURL portletURL =
237                            ((ActionResponseImpl)actionResponse).createRenderURL();
238    
239                    portletURL.setParameter(
240                            "struts_action", "/message_boards/edit_message");
241                    portletURL.setParameter("redirect", redirect);
242                    portletURL.setParameter(
243                            "messageId", String.valueOf(message.getMessageId()));
244                    portletURL.setParameter("preview", String.valueOf(preview));
245    
246                    return portletURL.toString();
247            }
248    
249            protected void lockThreads(ActionRequest actionRequest) throws Exception {
250                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
251    
252                    if (threadId > 0) {
253                            MBThreadServiceUtil.lockThread(threadId);
254                    }
255                    else {
256                            long[] threadIds = StringUtil.split(
257                                    ParamUtil.getString(actionRequest, "threadIds"), 0L);
258    
259                            for (int i = 0; i < threadIds.length; i++) {
260                                    MBThreadServiceUtil.lockThread(threadIds[i]);
261                            }
262                    }
263            }
264    
265            protected void subscribeMessage(ActionRequest actionRequest)
266                    throws Exception {
267    
268                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
269    
270                    MBMessageServiceUtil.subscribeMessage(messageId);
271            }
272    
273            protected void unlockThreads(ActionRequest actionRequest) throws Exception {
274                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
275    
276                    if (threadId > 0) {
277                            MBThreadServiceUtil.unlockThread(threadId);
278                    }
279                    else {
280                            long[] threadIds = StringUtil.split(
281                                    ParamUtil.getString(actionRequest, "threadIds"), 0L);
282    
283                            for (int i = 0; i < threadIds.length; i++) {
284                                    MBThreadServiceUtil.unlockThread(threadIds[i]);
285                            }
286                    }
287            }
288    
289            protected void unsubscribeMessage(ActionRequest actionRequest)
290                    throws Exception {
291    
292                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
293    
294                    MBMessageServiceUtil.unsubscribeMessage(messageId);
295            }
296    
297            protected MBMessage updateMessage(
298                            ActionRequest actionRequest, ActionResponse actionResponse)
299                    throws Exception {
300    
301                    PortletPreferences preferences = actionRequest.getPreferences();
302    
303                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
304                            WebKeys.THEME_DISPLAY);
305    
306                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
307    
308                    long groupId = themeDisplay.getScopeGroupId();
309                    long categoryId = ParamUtil.getLong(actionRequest, "mbCategoryId");
310                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
311                    long parentMessageId = ParamUtil.getLong(
312                            actionRequest, "parentMessageId");
313                    String subject = ParamUtil.getString(actionRequest, "subject");
314                    String body = ParamUtil.getString(actionRequest, "body");
315    
316                    String format = GetterUtil.getString(
317                            preferences.getValue("messageFormat", null),
318                            MBMessageConstants.DEFAULT_FORMAT);
319    
320                    boolean attachments = ParamUtil.getBoolean(
321                            actionRequest, "attachments");
322    
323                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
324                            new ArrayList<ObjectValuePair<String, InputStream>>(5);
325    
326                    try {
327                            if (attachments) {
328                                    UploadPortletRequest uploadPortletRequest =
329                                            PortalUtil.getUploadPortletRequest(actionRequest);
330    
331                                    for (int i = 1; i <= 5; i++) {
332                                            String fileName = uploadPortletRequest.getFileName(
333                                                    "msgFile" + i);
334                                            InputStream inputStream =
335                                                    uploadPortletRequest.getFileAsStream("msgFile" + i);
336    
337                                            if (inputStream == null) {
338                                                    continue;
339                                            }
340    
341                                            ObjectValuePair<String, InputStream> inputStreamOVP =
342                                                    new ObjectValuePair<String, InputStream>(
343                                                            fileName, inputStream);
344    
345                                            inputStreamOVPs.add(inputStreamOVP);
346                                    }
347                            }
348    
349                            boolean question = ParamUtil.getBoolean(actionRequest, "question");
350                            boolean anonymous = ParamUtil.getBoolean(
351                                    actionRequest, "anonymous");
352                            double priority = ParamUtil.getDouble(actionRequest, "priority");
353                            boolean allowPingbacks = ParamUtil.getBoolean(
354                                    actionRequest, "allowPingbacks");
355    
356                            ServiceContext serviceContext = ServiceContextFactory.getInstance(
357                                    MBMessage.class.getName(), actionRequest);
358    
359                            boolean preview = ParamUtil.getBoolean(actionRequest, "preview");
360    
361                            serviceContext.setAttribute("preview", preview);
362    
363                            MBMessage message = null;
364    
365                            if (messageId <= 0) {
366                                    if (PropsValues.
367                                                    CAPTCHA_CHECK_PORTLET_MESSAGE_BOARDS_EDIT_MESSAGE) {
368    
369                                            CaptchaUtil.check(actionRequest);
370                                    }
371    
372                                    if (threadId <= 0) {
373    
374                                            // Post new thread
375    
376                                            message = MBMessageServiceUtil.addMessage(
377                                                    groupId, categoryId, subject, body, format,
378                                                    inputStreamOVPs, anonymous, priority, allowPingbacks,
379                                                    serviceContext);
380    
381                                            if (question) {
382                                                    MBThreadLocalServiceUtil.updateQuestion(
383                                                            message.getThreadId(), true);
384                                            }
385                                    }
386                                    else {
387    
388                                            // Post reply
389    
390                                            message = MBMessageServiceUtil.addMessage(
391                                                    parentMessageId, subject, body, format, inputStreamOVPs,
392                                                    anonymous, priority, allowPingbacks, serviceContext);
393                                    }
394                            }
395                            else {
396                                    List<String> existingFiles = new ArrayList<String>();
397    
398                                    for (int i = 1; i <= 5; i++) {
399                                            String path = ParamUtil.getString(
400                                                    actionRequest, "existingPath" + i);
401    
402                                            if (Validator.isNotNull(path)) {
403                                                    existingFiles.add(path);
404                                            }
405                                    }
406    
407                                    // Update message
408    
409                                    message = MBMessageServiceUtil.updateMessage(
410                                            messageId, subject, body, inputStreamOVPs, existingFiles,
411                                            priority, allowPingbacks, serviceContext);
412    
413                                    if (message.isRoot()) {
414                                            MBThreadLocalServiceUtil.updateQuestion(
415                                                    message.getThreadId(), question);
416                                    }
417                            }
418    
419                            PermissionChecker permissionChecker =
420                                    themeDisplay.getPermissionChecker();
421    
422                            boolean subscribe = ParamUtil.getBoolean(
423                                    actionRequest, "subscribe");
424    
425                            if (!preview && subscribe &&
426                                    MBMessagePermission.contains(
427                                            permissionChecker, message, ActionKeys.SUBSCRIBE)) {
428    
429                                    MBMessageServiceUtil.subscribeMessage(message.getMessageId());
430                            }
431    
432                            return message;
433                    }
434                    finally {
435                            if (attachments) {
436                                    for (ObjectValuePair<String, InputStream> inputStreamOVP :
437                                                    inputStreamOVPs) {
438    
439                                            InputStream inputStream = inputStreamOVP.getValue();
440    
441                                            StreamUtil.cleanUp(inputStream);
442                                    }
443                            }
444                    }
445            }
446    
447    }