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