001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.action;
016    
017    import com.liferay.portal.LocaleException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.portlet.LiferayWindowState;
020    import com.liferay.portal.kernel.servlet.SessionErrors;
021    import com.liferay.portal.kernel.servlet.SessionMessages;
022    import com.liferay.portal.kernel.upload.UploadException;
023    import com.liferay.portal.kernel.upload.UploadPortletRequest;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.Constants;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.HttpUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.LocalizationUtil;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.StringPool;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.workflow.WorkflowConstants;
035    import com.liferay.portal.model.Layout;
036    import com.liferay.portal.security.auth.PrincipalException;
037    import com.liferay.portal.service.LayoutLocalServiceUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.ServiceContextFactory;
040    import com.liferay.portal.struts.PortletAction;
041    import com.liferay.portal.theme.ThemeDisplay;
042    import com.liferay.portal.util.PortalUtil;
043    import com.liferay.portal.util.WebKeys;
044    import com.liferay.portlet.PortletURLFactoryUtil;
045    import com.liferay.portlet.PortletURLImpl;
046    import com.liferay.portlet.asset.AssetCategoryException;
047    import com.liferay.portlet.asset.AssetTagException;
048    import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
049    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
050    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
052    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
053    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
054    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
055    import com.liferay.portlet.journal.ArticleContentException;
056    import com.liferay.portlet.journal.ArticleContentSizeException;
057    import com.liferay.portlet.journal.ArticleDisplayDateException;
058    import com.liferay.portlet.journal.ArticleExpirationDateException;
059    import com.liferay.portlet.journal.ArticleIdException;
060    import com.liferay.portlet.journal.ArticleSmallImageNameException;
061    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
062    import com.liferay.portlet.journal.ArticleTitleException;
063    import com.liferay.portlet.journal.ArticleTypeException;
064    import com.liferay.portlet.journal.ArticleVersionException;
065    import com.liferay.portlet.journal.DuplicateArticleIdException;
066    import com.liferay.portlet.journal.NoSuchArticleException;
067    import com.liferay.portlet.journal.asset.JournalArticleAssetRenderer;
068    import com.liferay.portlet.journal.model.JournalArticle;
069    import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
070    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
071    import com.liferay.portlet.journal.util.JournalConverterUtil;
072    import com.liferay.portlet.journal.util.JournalUtil;
073    
074    import java.io.File;
075    
076    import java.util.Calendar;
077    import java.util.HashMap;
078    import java.util.Locale;
079    import java.util.Map;
080    
081    import javax.portlet.ActionRequest;
082    import javax.portlet.ActionResponse;
083    import javax.portlet.PortletConfig;
084    import javax.portlet.PortletPreferences;
085    import javax.portlet.PortletRequest;
086    import javax.portlet.PortletURL;
087    import javax.portlet.RenderRequest;
088    import javax.portlet.RenderResponse;
089    import javax.portlet.WindowState;
090    
091    import org.apache.struts.action.ActionForm;
092    import org.apache.struts.action.ActionForward;
093    import org.apache.struts.action.ActionMapping;
094    
095    /**
096     * @author Brian Wing Shun Chan
097     * @author Raymond Aug??
098     * @author Eduardo Lundgren
099     * @author Juan Fern??ndez
100     * @author Levente Hud??k
101     */
102    public class EditArticleAction extends PortletAction {
103    
104            public static final String VERSION_SEPARATOR = "_version_";
105    
106            @Override
107            public void processAction(
108                            ActionMapping actionMapping, ActionForm actionForm,
109                            PortletConfig portletConfig, ActionRequest actionRequest,
110                            ActionResponse actionResponse)
111                    throws Exception {
112    
113                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
114    
115                    JournalArticle article = null;
116                    String oldUrlTitle = StringPool.BLANK;
117    
118                    try {
119                            if (Validator.isNull(cmd)) {
120                                    UploadException uploadException =
121                                            (UploadException)actionRequest.getAttribute(
122                                                    WebKeys.UPLOAD_EXCEPTION);
123    
124                                    if (uploadException != null) {
125                                            if (uploadException.isExceededSizeLimit()) {
126                                                    throw new ArticleContentSizeException();
127                                            }
128    
129                                            throw new PortalException(uploadException.getCause());
130                                    }
131    
132                                    return;
133                            }
134                            else if (cmd.equals(Constants.ADD) ||
135                                             cmd.equals(Constants.PREVIEW) ||
136                                             cmd.equals(Constants.TRANSLATE) ||
137                                             cmd.equals(Constants.UPDATE)) {
138    
139                                    Object[] contentAndImages = updateArticle(actionRequest);
140    
141                                    article = (JournalArticle)contentAndImages[0];
142                                    oldUrlTitle = ((String)contentAndImages[1]);
143                            }
144                            else if (cmd.equals(Constants.DELETE)) {
145                                    deleteArticles(actionRequest, false);
146                            }
147                            else if (cmd.equals(Constants.DELETE_TRANSLATION)) {
148                                    removeArticlesLocale(actionRequest);
149                            }
150                            else if (cmd.equals(Constants.EXPIRE)) {
151                                    expireArticles(actionRequest);
152                            }
153                            else if (cmd.equals(Constants.MOVE)) {
154                                    moveArticles(actionRequest);
155                            }
156                            else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
157                                    deleteArticles(actionRequest, true);
158                            }
159                            else if (cmd.equals(Constants.RESTORE)) {
160                                    restoreArticles(actionRequest);
161                            }
162                            else if (cmd.equals(Constants.SUBSCRIBE)) {
163                                    subscribeArticles(actionRequest);
164                            }
165                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
166                                    unsubscribeArticles(actionRequest);
167                            }
168    
169                            String redirect = ParamUtil.getString(actionRequest, "redirect");
170    
171                            int workflowAction = ParamUtil.getInteger(
172                                    actionRequest, "workflowAction",
173                                    WorkflowConstants.ACTION_PUBLISH);
174    
175                            String portletId = HttpUtil.getParameter(redirect, "p_p_id", false);
176    
177                            String namespace = PortalUtil.getPortletNamespace(portletId);
178    
179                            if (Validator.isNotNull(oldUrlTitle)) {
180                                    String oldRedirectParam = namespace + "redirect";
181    
182                                    String oldRedirect = HttpUtil.getParameter(
183                                            redirect, oldRedirectParam, false);
184    
185                                    if (Validator.isNotNull(oldRedirect)) {
186                                            String newRedirect = HttpUtil.decodeURL(oldRedirect);
187    
188                                            newRedirect = StringUtil.replace(
189                                                    newRedirect, oldUrlTitle, article.getUrlTitle());
190                                            newRedirect = StringUtil.replace(
191                                                    newRedirect, oldRedirectParam, "redirect");
192    
193                                            redirect = StringUtil.replace(
194                                                    redirect, oldRedirect, newRedirect);
195                                    }
196                            }
197    
198                            ThemeDisplay themeDisplay =
199                                    (ThemeDisplay)actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
200    
201                            if (cmd.equals(Constants.DELETE) &&
202                                    !ActionUtil.hasArticle(actionRequest)) {
203    
204                                    String referringPortletResource = ParamUtil.getString(
205                                            actionRequest, "referringPortletResource");
206    
207                                    if (Validator.isNotNull(referringPortletResource)) {
208                                            setForward(
209                                                    actionRequest,
210                                                    "portlet.journal.asset.add_asset_redirect");
211    
212                                            return;
213                                    }
214                                    else {
215                                            PortletURL portletURL = PortletURLFactoryUtil.create(
216                                                    actionRequest, portletConfig.getPortletName(),
217                                                    themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
218    
219                                            redirect = portletURL.toString();
220                                    }
221                            }
222    
223                            if (cmd.equals(Constants.DELETE_TRANSLATION) ||
224                                    cmd.equals(Constants.TRANSLATE)) {
225    
226                                    setForward(
227                                            actionRequest,
228                                            "portlet.journal.update_translation_redirect");
229                            }
230                            else if ((article != null) &&
231                                             (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT)) {
232    
233                                    redirect = getSaveAndContinueRedirect(
234                                            portletConfig, actionRequest, article, redirect);
235    
236                                    sendRedirect(actionRequest, actionResponse, redirect);
237                            }
238                            else {
239                                    WindowState windowState = actionRequest.getWindowState();
240    
241                                    Layout layout = themeDisplay.getLayout();
242    
243                                    if (!windowState.equals(LiferayWindowState.POP_UP) &&
244                                            layout.isTypeControlPanel()) {
245    
246                                            sendRedirect(actionRequest, actionResponse, redirect);
247                                    }
248                                    else {
249                                            redirect = PortalUtil.escapeRedirect(redirect);
250    
251                                            if (Validator.isNotNull(redirect)) {
252                                                    if (cmd.equals(Constants.ADD) && (article != null)) {
253                                                            redirect = HttpUtil.addParameter(
254                                                                    redirect, namespace + "className",
255                                                                    JournalArticle.class.getName());
256                                                            redirect = HttpUtil.addParameter(
257                                                                    redirect, namespace + "classPK",
258                                                                    JournalArticleAssetRenderer.getClassPK(
259                                                                            article));
260                                                    }
261    
262                                                    actionResponse.sendRedirect(redirect);
263                                            }
264                                    }
265                            }
266                    }
267                    catch (Exception e) {
268                            if (e instanceof NoSuchArticleException ||
269                                    e instanceof NoSuchStructureException ||
270                                    e instanceof NoSuchTemplateException ||
271                                    e instanceof PrincipalException) {
272    
273                                    SessionErrors.add(actionRequest, e.getClass());
274    
275                                    setForward(actionRequest, "portlet.journal.error");
276                            }
277                            else if (e instanceof ArticleContentException ||
278                                             e instanceof ArticleContentSizeException ||
279                                             e instanceof ArticleDisplayDateException ||
280                                             e instanceof ArticleExpirationDateException ||
281                                             e instanceof ArticleIdException ||
282                                             e instanceof ArticleSmallImageNameException ||
283                                             e instanceof ArticleSmallImageSizeException ||
284                                             e instanceof ArticleTitleException ||
285                                             e instanceof ArticleTypeException ||
286                                             e instanceof ArticleVersionException ||
287                                             e instanceof DuplicateArticleIdException) {
288    
289                                    SessionErrors.add(actionRequest, e.getClass());
290                            }
291                            else if (e instanceof AssetCategoryException ||
292                                             e instanceof AssetTagException ||
293                                             e instanceof LocaleException) {
294    
295                                    SessionErrors.add(actionRequest, e.getClass(), e);
296                            }
297                            else {
298                                    throw e;
299                            }
300                    }
301            }
302    
303            @Override
304            public ActionForward render(
305                            ActionMapping actionMapping, ActionForm actionForm,
306                            PortletConfig portletConfig, RenderRequest renderRequest,
307                            RenderResponse renderResponse)
308                    throws Exception {
309    
310                    try {
311                            ActionUtil.getArticle(renderRequest);
312                    }
313                    catch (NoSuchArticleException nsae) {
314    
315                            // Let this slide because the user can manually input a article id
316                            // for a new article that does not yet exist.
317    
318                    }
319                    catch (Exception e) {
320                            if (//e instanceof NoSuchArticleException ||
321                                    e instanceof PrincipalException) {
322    
323                                    SessionErrors.add(renderRequest, e.getClass());
324    
325                                    return actionMapping.findForward("portlet.journal.error");
326                            }
327                            else {
328                                    throw e;
329                            }
330                    }
331    
332                    return actionMapping.findForward(
333                            getForward(renderRequest, "portlet.journal.edit_article"));
334            }
335    
336            protected void deleteArticles(
337                            ActionRequest actionRequest, boolean moveToTrash)
338                    throws Exception {
339    
340                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
341                            WebKeys.THEME_DISPLAY);
342    
343                    String deleteEntryTitle = null;
344    
345                    String[] deleteArticleIds = null;
346    
347                    String articleId = ParamUtil.getString(actionRequest, "articleId");
348    
349                    if (Validator.isNotNull(articleId)) {
350                            deleteArticleIds = new String[] {articleId};
351                    }
352                    else {
353                            deleteArticleIds = StringUtil.split(
354                                    ParamUtil.getString(actionRequest, "articleIds"));
355                    }
356    
357                    long[] restoreArticleIds = new long[deleteArticleIds.length];
358    
359                    for (int i = 0; i < deleteArticleIds.length; i++) {
360                            String deleteArticleId = deleteArticleIds[i];
361    
362                            if (moveToTrash) {
363                                    JournalArticle article =
364                                            JournalArticleServiceUtil.moveArticleToTrash(
365                                                    themeDisplay.getScopeGroupId(), deleteArticleId);
366    
367                                    if (i == 0) {
368                                            deleteEntryTitle = article.getTitle(
369                                                    themeDisplay.getLocale());
370                                    }
371    
372                                    restoreArticleIds[i] = article.getResourcePrimKey();
373                            }
374                            else {
375                                    ActionUtil.deleteArticle(actionRequest, deleteArticleId);
376                            }
377                    }
378    
379                    if (moveToTrash && (deleteArticleIds.length > 0)) {
380                            Map<String, String[]> data = new HashMap<String, String[]>();
381    
382                            data.put(
383                                    "deleteEntryClassName",
384                                    new String[] {JournalArticle.class.getName()});
385    
386                            if (Validator.isNotNull(deleteEntryTitle)) {
387                                    data.put("deleteEntryTitle", new String[] {deleteEntryTitle});
388                            }
389    
390                            data.put(
391                                    "restoreArticleIds",
392                                    ArrayUtil.toStringArray(restoreArticleIds));
393    
394                            SessionMessages.add(
395                                    actionRequest,
396                                    PortalUtil.getPortletId(actionRequest) +
397                                            SessionMessages.KEY_SUFFIX_DELETE_SUCCESS_DATA, data);
398    
399                            hideDefaultSuccessMessage(actionRequest);
400                    }
401            }
402    
403            protected void expireArticles(ActionRequest actionRequest)
404                    throws Exception {
405    
406                    String articleId = ParamUtil.getString(actionRequest, "articleId");
407    
408                    if (Validator.isNotNull(articleId)) {
409                            ActionUtil.expireArticle(actionRequest, articleId);
410                    }
411                    else {
412                            String[] expireArticleIds = StringUtil.split(
413                                    ParamUtil.getString(actionRequest, "expireArticleIds"));
414    
415                            for (String expireArticleId : expireArticleIds) {
416                                    ActionUtil.expireArticle(actionRequest, expireArticleId);
417                            }
418                    }
419            }
420    
421            protected String getSaveAndContinueRedirect(
422                            PortletConfig portletConfig, ActionRequest actionRequest,
423                            JournalArticle article, String redirect)
424                    throws Exception {
425    
426                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
427                            WebKeys.THEME_DISPLAY);
428    
429                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
430    
431                    String referringPortletResource = ParamUtil.getString(
432                            actionRequest, "referringPortletResource");
433    
434                    String languageId = ParamUtil.getString(actionRequest, "languageId");
435    
436                    PortletURLImpl portletURL = new PortletURLImpl(
437                            actionRequest, portletConfig.getPortletName(),
438                            themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
439    
440                    portletURL.setParameter("struts_action", "/journal/edit_article");
441                    portletURL.setParameter(Constants.CMD, cmd, false);
442                    portletURL.setParameter("redirect", redirect, false);
443                    portletURL.setParameter(
444                            "referringPortletResource", referringPortletResource, false);
445                    portletURL.setParameter(
446                            "resourcePrimKey", String.valueOf(article.getResourcePrimKey()),
447                            false);
448                    portletURL.setParameter(
449                            "groupId", String.valueOf(article.getGroupId()), false);
450                    portletURL.setParameter("articleId", article.getArticleId(), false);
451                    portletURL.setParameter(
452                            "version", String.valueOf(article.getVersion()), false);
453                    portletURL.setParameter("languageId", languageId, false);
454                    portletURL.setWindowState(actionRequest.getWindowState());
455    
456                    return portletURL.toString();
457            }
458    
459            protected void moveArticles(ActionRequest actionRequest) throws Exception {
460                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
461                            WebKeys.THEME_DISPLAY);
462    
463                    String articleId = ParamUtil.getString(actionRequest, "articleId");
464                    long newFolderId = ParamUtil.getLong(actionRequest, "newFolderId");
465    
466                    if (Validator.isNotNull(articleId)) {
467                            JournalArticleServiceUtil.moveArticle(
468                                    themeDisplay.getScopeGroupId(), articleId, newFolderId);
469                    }
470                    else {
471                            String[] articleIds = StringUtil.split(
472                                    ParamUtil.getString(actionRequest, "articleIds"));
473    
474                            for (int i = 0; i < articleIds.length; i++) {
475                                    JournalArticleServiceUtil.moveArticle(
476                                            themeDisplay.getScopeGroupId(), articleIds[i], newFolderId);
477                            }
478                    }
479            }
480    
481            protected void removeArticlesLocale(ActionRequest actionRequest)
482                    throws Exception {
483    
484                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
485    
486                    String[] removeArticleLocaleIds = StringUtil.split(
487                            ParamUtil.getString(actionRequest, "articleIds"));
488    
489                    for (String removeArticleLocaleId : removeArticleLocaleIds) {
490                            int pos = removeArticleLocaleId.lastIndexOf(VERSION_SEPARATOR);
491    
492                            String articleId = removeArticleLocaleId.substring(0, pos);
493                            double version = GetterUtil.getDouble(
494                                    removeArticleLocaleId.substring(
495                                            pos + VERSION_SEPARATOR.length()));
496                            String languageId = ParamUtil.getString(
497                                    actionRequest, "languageId");
498    
499                            JournalArticleServiceUtil.removeArticleLocale(
500                                    groupId, articleId, version, languageId);
501                    }
502            }
503    
504            protected void restoreArticles(ActionRequest actionRequest)
505                    throws Exception {
506    
507                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
508                            WebKeys.THEME_DISPLAY);
509    
510                    String[] restoreEntryIds = StringUtil.split(
511                            ParamUtil.getString(actionRequest, "restoreEntryIds"));
512    
513                    for (String restoreEntryId : restoreEntryIds) {
514                            JournalArticleServiceUtil.restoreArticleFromTrash(
515                                    themeDisplay.getScopeGroupId(), restoreEntryId);
516                    }
517            }
518    
519            protected void subscribeArticles(ActionRequest actionRequest)
520                    throws Exception {
521    
522                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
523                            WebKeys.THEME_DISPLAY);
524    
525                    JournalArticleServiceUtil.subscribe(themeDisplay.getScopeGroupId());
526            }
527    
528            protected void unsubscribeArticles(ActionRequest actionRequest)
529                    throws Exception {
530    
531                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
532                            WebKeys.THEME_DISPLAY);
533    
534                    JournalArticleServiceUtil.unsubscribe(themeDisplay.getScopeGroupId());
535            }
536    
537            protected Object[] updateArticle(ActionRequest actionRequest)
538                    throws Exception {
539    
540                    UploadPortletRequest uploadPortletRequest =
541                            PortalUtil.getUploadPortletRequest(actionRequest);
542    
543                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
544    
545                    long groupId = ParamUtil.getLong(uploadPortletRequest, "groupId");
546                    long folderId = ParamUtil.getLong(uploadPortletRequest, "folderId");
547                    long classNameId = ParamUtil.getLong(
548                            uploadPortletRequest, "classNameId");
549                    long classPK = ParamUtil.getLong(uploadPortletRequest, "classPK");
550    
551                    String articleId = ParamUtil.getString(
552                            uploadPortletRequest, "articleId");
553    
554                    boolean autoArticleId = ParamUtil.getBoolean(
555                            uploadPortletRequest, "autoArticleId");
556                    double version = ParamUtil.getDouble(uploadPortletRequest, "version");
557                    boolean localized = ParamUtil.getBoolean(
558                            uploadPortletRequest, "localized");
559    
560                    String defaultLanguageId = ParamUtil.getString(
561                            uploadPortletRequest, "defaultLanguageId");
562    
563                    Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
564    
565                    String toLanguageId = ParamUtil.getString(
566                            uploadPortletRequest, "toLanguageId");
567    
568                    Locale toLocale = null;
569    
570                    String title = StringPool.BLANK;
571                    String description = StringPool.BLANK;
572    
573                    if (Validator.isNull(toLanguageId)) {
574                            title = ParamUtil.getString(
575                                    uploadPortletRequest, "title_" + defaultLanguageId);
576                            description = ParamUtil.getString(
577                                    uploadPortletRequest, "description_" + defaultLanguageId);
578                    }
579                    else {
580                            toLocale = LocaleUtil.fromLanguageId(toLanguageId);
581    
582                            title = ParamUtil.getString(
583                                    uploadPortletRequest, "title_" + toLanguageId);
584                            description = ParamUtil.getString(
585                                    uploadPortletRequest, "description_" + toLanguageId);
586                    }
587    
588                    String content = ParamUtil.getString(
589                            uploadPortletRequest, "articleContent");
590    
591                    Map<String, byte[]> images = new HashMap<String, byte[]>();
592    
593                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
594                            JournalArticle.class.getName(), uploadPortletRequest);
595    
596                    String structureId = ParamUtil.getString(
597                            uploadPortletRequest, "structureId");
598    
599                    DDMStructure ddmStructure = null;
600    
601                    if (Validator.isNotNull(structureId)) {
602                            ddmStructure = DDMStructureLocalServiceUtil.getStructure(
603                                    PortalUtil.getSiteGroupId(groupId),
604                                    PortalUtil.getClassNameId(JournalArticle.class), structureId,
605                                    true);
606    
607                            String languageId = toLanguageId;
608    
609                            if (Validator.isNull(languageId)) {
610                                    languageId = defaultLanguageId;
611                            }
612    
613                            Locale locale = LocaleUtil.fromLanguageId(languageId);
614    
615                            Object[] contentAndImages = ActionUtil.getContentAndImages(
616                                    ddmStructure, locale, serviceContext);
617    
618                            content = (String)contentAndImages[0];
619                            images = (HashMap<String, byte[]>)contentAndImages[1];
620                    }
621    
622                    Boolean fileItemThresholdSizeExceeded =
623                            (Boolean)uploadPortletRequest.getAttribute(
624                                    WebKeys.FILE_ITEM_THRESHOLD_SIZE_EXCEEDED);
625    
626                    if ((fileItemThresholdSizeExceeded != null) &&
627                            fileItemThresholdSizeExceeded.booleanValue()) {
628    
629                            throw new ArticleContentSizeException();
630                    }
631    
632                    String type = ParamUtil.getString(uploadPortletRequest, "type");
633                    String templateId = ParamUtil.getString(
634                            uploadPortletRequest, "templateId");
635                    String layoutUuid = ParamUtil.getString(
636                            uploadPortletRequest, "layoutUuid");
637    
638                    // The target page and the article must belong to the same group
639    
640                    Layout targetLayout =
641                            LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
642                                    layoutUuid, groupId, false);
643    
644                    if (targetLayout == null) {
645                            targetLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
646                                    layoutUuid, groupId, true);
647                    }
648    
649                    if (targetLayout == null) {
650                            layoutUuid = null;
651                    }
652    
653                    int displayDateMonth = ParamUtil.getInteger(
654                            uploadPortletRequest, "displayDateMonth");
655                    int displayDateDay = ParamUtil.getInteger(
656                            uploadPortletRequest, "displayDateDay");
657                    int displayDateYear = ParamUtil.getInteger(
658                            uploadPortletRequest, "displayDateYear");
659                    int displayDateHour = ParamUtil.getInteger(
660                            uploadPortletRequest, "displayDateHour");
661                    int displayDateMinute = ParamUtil.getInteger(
662                            uploadPortletRequest, "displayDateMinute");
663                    int displayDateAmPm = ParamUtil.getInteger(
664                            uploadPortletRequest, "displayDateAmPm");
665    
666                    if (displayDateAmPm == Calendar.PM) {
667                            displayDateHour += 12;
668                    }
669    
670                    int expirationDateMonth = ParamUtil.getInteger(
671                            uploadPortletRequest, "expirationDateMonth");
672                    int expirationDateDay = ParamUtil.getInteger(
673                            uploadPortletRequest, "expirationDateDay");
674                    int expirationDateYear = ParamUtil.getInteger(
675                            uploadPortletRequest, "expirationDateYear");
676                    int expirationDateHour = ParamUtil.getInteger(
677                            uploadPortletRequest, "expirationDateHour");
678                    int expirationDateMinute = ParamUtil.getInteger(
679                            uploadPortletRequest, "expirationDateMinute");
680                    int expirationDateAmPm = ParamUtil.getInteger(
681                            uploadPortletRequest, "expirationDateAmPm");
682                    boolean neverExpire = ParamUtil.getBoolean(
683                            uploadPortletRequest, "neverExpire");
684    
685                    if (expirationDateAmPm == Calendar.PM) {
686                            expirationDateHour += 12;
687                    }
688    
689                    int reviewDateMonth = ParamUtil.getInteger(
690                            uploadPortletRequest, "reviewDateMonth");
691                    int reviewDateDay = ParamUtil.getInteger(
692                            uploadPortletRequest, "reviewDateDay");
693                    int reviewDateYear = ParamUtil.getInteger(
694                            uploadPortletRequest, "reviewDateYear");
695                    int reviewDateHour = ParamUtil.getInteger(
696                            uploadPortletRequest, "reviewDateHour");
697                    int reviewDateMinute = ParamUtil.getInteger(
698                            uploadPortletRequest, "reviewDateMinute");
699                    int reviewDateAmPm = ParamUtil.getInteger(
700                            uploadPortletRequest, "reviewDateAmPm");
701                    boolean neverReview = ParamUtil.getBoolean(
702                            uploadPortletRequest, "neverReview");
703    
704                    if (reviewDateAmPm == Calendar.PM) {
705                            reviewDateHour += 12;
706                    }
707    
708                    boolean indexable = ParamUtil.getBoolean(
709                            uploadPortletRequest, "indexable");
710    
711                    boolean smallImage = ParamUtil.getBoolean(
712                            uploadPortletRequest, "smallImage");
713                    String smallImageURL = ParamUtil.getString(
714                            uploadPortletRequest, "smallImageURL");
715                    File smallFile = uploadPortletRequest.getFile("smallFile");
716    
717                    String articleURL = ParamUtil.getString(
718                            uploadPortletRequest, "articleURL");
719    
720                    serviceContext.setAttribute("defaultLanguageId", defaultLanguageId);
721    
722                    JournalArticle article = null;
723                    String oldUrlTitle = StringPool.BLANK;
724    
725                    if (cmd.equals(Constants.ADD)) {
726                            Map<Locale, String> titleMap = new HashMap<Locale, String>();
727    
728                            titleMap.put(defaultLocale, title);
729    
730                            Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
731    
732                            descriptionMap.put(defaultLocale, description);
733    
734                            if (Validator.isNull(structureId)) {
735                                    content = LocalizationUtil.updateLocalization(
736                                            StringPool.BLANK, "static-content", content,
737                                            defaultLanguageId, defaultLanguageId, true, localized);
738                            }
739    
740                            // Add article
741    
742                            article = JournalArticleServiceUtil.addArticle(
743                                    groupId, folderId, classNameId, classPK, articleId,
744                                    autoArticleId, titleMap, descriptionMap, content, type,
745                                    structureId, templateId, layoutUuid, displayDateMonth,
746                                    displayDateDay, displayDateYear, displayDateHour,
747                                    displayDateMinute, expirationDateMonth, expirationDateDay,
748                                    expirationDateYear, expirationDateHour, expirationDateMinute,
749                                    neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
750                                    reviewDateHour, reviewDateMinute, neverReview, indexable,
751                                    smallImage, smallImageURL, smallFile, images, articleURL,
752                                    serviceContext);
753    
754                            AssetPublisherUtil.addAndStoreSelection(
755                                    actionRequest, JournalArticle.class.getName(),
756                                    article.getResourcePrimKey(), -1);
757                    }
758                    else {
759    
760                            // Merge current content with new content
761    
762                            JournalArticle curArticle = JournalArticleServiceUtil.getArticle(
763                                    groupId, articleId, version);
764    
765                            if (Validator.isNull(structureId)) {
766                                    if (!curArticle.isTemplateDriven()) {
767                                            String curContent = StringPool.BLANK;
768    
769                                            curContent = curArticle.getContent();
770    
771                                            if (cmd.equals(Constants.TRANSLATE)) {
772                                                    content = LocalizationUtil.updateLocalization(
773                                                            curContent, "static-content", content, toLanguageId,
774                                                            defaultLanguageId, true, true);
775                                            }
776                                            else {
777                                                    content = LocalizationUtil.updateLocalization(
778                                                            curContent, "static-content", content,
779                                                            defaultLanguageId, defaultLanguageId, true,
780                                                            localized);
781                                            }
782                                    }
783                            }
784                            else {
785                                    if (curArticle.isTemplateDriven()) {
786                                            Fields newFields = DDMUtil.getFields(
787                                                    ddmStructure.getStructureId(), serviceContext);
788    
789                                            Fields existingFields = JournalConverterUtil.getDDMFields(
790                                                    ddmStructure, curArticle.getContent());
791    
792                                            Fields mergedFields = DDMUtil.mergeFields(
793                                                    newFields, existingFields);
794    
795                                            content = JournalConverterUtil.getContent(
796                                                    ddmStructure, mergedFields);
797                                    }
798                            }
799    
800                            // Update article
801    
802                            article = JournalArticleServiceUtil.getArticle(
803                                    groupId, articleId, version);
804    
805                            Map<Locale, String> titleMap = article.getTitleMap();
806                            Map<Locale, String> descriptionMap = article.getDescriptionMap();
807    
808                            String tempOldUrlTitle = article.getUrlTitle();
809    
810                            if (cmd.equals(Constants.PREVIEW) || cmd.equals(Constants.UPDATE)) {
811                                    titleMap.put(defaultLocale, title);
812                                    descriptionMap.put(defaultLocale, description);
813    
814                                    article = JournalArticleServiceUtil.updateArticle(
815                                            groupId, folderId, articleId, version, titleMap,
816                                            descriptionMap, content, type, structureId, templateId,
817                                            layoutUuid, displayDateMonth, displayDateDay,
818                                            displayDateYear, displayDateHour, displayDateMinute,
819                                            expirationDateMonth, expirationDateDay, expirationDateYear,
820                                            expirationDateHour, expirationDateMinute, neverExpire,
821                                            reviewDateMonth, reviewDateDay, reviewDateYear,
822                                            reviewDateHour, reviewDateMinute, neverReview, indexable,
823                                            smallImage, smallImageURL, smallFile, images, articleURL,
824                                            serviceContext);
825                            }
826                            else if (cmd.equals(Constants.TRANSLATE)) {
827                                    article = JournalArticleServiceUtil.updateArticleTranslation(
828                                            groupId, articleId, version, toLocale, title, description,
829                                            content, images, serviceContext);
830                            }
831    
832                            if (!tempOldUrlTitle.equals(article.getUrlTitle())) {
833                                    oldUrlTitle = tempOldUrlTitle;
834                            }
835                    }
836    
837                    // Recent articles
838    
839                    JournalUtil.addRecentArticle(actionRequest, article);
840    
841                    // Journal content
842    
843                    PortletPreferences portletPreferences = getStrictPortletSetup(
844                            actionRequest);
845    
846                    if (portletPreferences != null) {
847                            portletPreferences.setValue(
848                                    "groupId", String.valueOf(article.getGroupId()));
849                            portletPreferences.setValue("articleId", article.getArticleId());
850    
851                            portletPreferences.store();
852    
853                            String portletResource = ParamUtil.getString(
854                                    actionRequest, "portletResource");
855    
856                            updateContentSearch(
857                                    actionRequest, portletResource, article.getArticleId());
858                    }
859    
860                    return new Object[] {article, oldUrlTitle};
861            }
862    
863            protected void updateContentSearch(
864                            ActionRequest actionRequest, String portletResource,
865                            String articleId)
866                    throws Exception {
867    
868                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
869                            WebKeys.THEME_DISPLAY);
870    
871                    Layout layout = themeDisplay.getLayout();
872    
873                    JournalContentSearchLocalServiceUtil.updateContentSearch(
874                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
875                            portletResource, articleId, true);
876            }
877    
878    }