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