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