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