001    /**
002     * Copyright (c) 2000-present 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.exportimport.staging;
016    
017    import com.liferay.portal.LayoutPrototypeException;
018    import com.liferay.portal.LocaleException;
019    import com.liferay.portal.NoSuchGroupException;
020    import com.liferay.portal.NoSuchLayoutBranchException;
021    import com.liferay.portal.NoSuchLayoutRevisionException;
022    import com.liferay.portal.PortletIdException;
023    import com.liferay.portal.RemoteOptionsException;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.json.JSONArray;
027    import com.liferay.portal.kernel.json.JSONException;
028    import com.liferay.portal.kernel.json.JSONFactoryUtil;
029    import com.liferay.portal.kernel.json.JSONObject;
030    import com.liferay.portal.kernel.language.LanguageUtil;
031    import com.liferay.portal.kernel.lock.DuplicateLockException;
032    import com.liferay.portal.kernel.lock.Lock;
033    import com.liferay.portal.kernel.lock.LockManagerUtil;
034    import com.liferay.portal.kernel.log.Log;
035    import com.liferay.portal.kernel.log.LogFactoryUtil;
036    import com.liferay.portal.kernel.messaging.DestinationNames;
037    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
038    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
039    import com.liferay.portal.kernel.servlet.ServletResponseConstants;
040    import com.liferay.portal.kernel.util.Constants;
041    import com.liferay.portal.kernel.util.GetterUtil;
042    import com.liferay.portal.kernel.util.Http;
043    import com.liferay.portal.kernel.util.MapUtil;
044    import com.liferay.portal.kernel.util.ParamUtil;
045    import com.liferay.portal.kernel.util.PropsKeys;
046    import com.liferay.portal.kernel.util.StringBundler;
047    import com.liferay.portal.kernel.util.StringPool;
048    import com.liferay.portal.kernel.util.StringUtil;
049    import com.liferay.portal.kernel.util.TextFormatter;
050    import com.liferay.portal.kernel.util.Tuple;
051    import com.liferay.portal.kernel.util.UnicodeProperties;
052    import com.liferay.portal.kernel.util.Validator;
053    import com.liferay.portal.kernel.workflow.WorkflowConstants;
054    import com.liferay.portal.kernel.workflow.WorkflowTask;
055    import com.liferay.portal.kernel.workflow.WorkflowTaskManagerUtil;
056    import com.liferay.portal.kernel.xml.Element;
057    import com.liferay.portal.model.ClassName;
058    import com.liferay.portal.model.Company;
059    import com.liferay.portal.model.Group;
060    import com.liferay.portal.model.GroupConstants;
061    import com.liferay.portal.model.Layout;
062    import com.liferay.portal.model.LayoutBranch;
063    import com.liferay.portal.model.LayoutRevision;
064    import com.liferay.portal.model.Portlet;
065    import com.liferay.portal.model.StagedModel;
066    import com.liferay.portal.model.User;
067    import com.liferay.portal.model.WorkflowInstanceLink;
068    import com.liferay.portal.model.adapter.StagedTheme;
069    import com.liferay.portal.security.auth.HttpPrincipal;
070    import com.liferay.portal.security.auth.PrincipalException;
071    import com.liferay.portal.security.auth.RemoteAuthException;
072    import com.liferay.portal.security.permission.ActionKeys;
073    import com.liferay.portal.security.permission.PermissionChecker;
074    import com.liferay.portal.security.permission.PermissionThreadLocal;
075    import com.liferay.portal.security.permission.ResourceActionsUtil;
076    import com.liferay.portal.service.BackgroundTaskLocalServiceUtil;
077    import com.liferay.portal.service.GroupLocalServiceUtil;
078    import com.liferay.portal.service.LayoutBranchLocalServiceUtil;
079    import com.liferay.portal.service.LayoutLocalServiceUtil;
080    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
081    import com.liferay.portal.service.LayoutServiceUtil;
082    import com.liferay.portal.service.ServiceContext;
083    import com.liferay.portal.service.ServiceContextThreadLocal;
084    import com.liferay.portal.service.UserLocalServiceUtil;
085    import com.liferay.portal.service.WorkflowInstanceLinkLocalServiceUtil;
086    import com.liferay.portal.service.http.ClassNameServiceHttp;
087    import com.liferay.portal.service.http.GroupServiceHttp;
088    import com.liferay.portal.service.permission.GroupPermissionUtil;
089    import com.liferay.portal.theme.ThemeDisplay;
090    import com.liferay.portal.util.PortalUtil;
091    import com.liferay.portal.util.PrefsPropsUtil;
092    import com.liferay.portal.util.PropsValues;
093    import com.liferay.portal.util.SessionClicks;
094    import com.liferay.portal.util.WebKeys;
095    import com.liferay.portlet.PortalPreferences;
096    import com.liferay.portlet.PortletPreferencesFactoryUtil;
097    import com.liferay.portlet.documentlibrary.DuplicateFileException;
098    import com.liferay.portlet.documentlibrary.FileExtensionException;
099    import com.liferay.portlet.documentlibrary.FileNameException;
100    import com.liferay.portlet.documentlibrary.FileSizeException;
101    import com.liferay.portlet.exportimport.LARFileException;
102    import com.liferay.portlet.exportimport.LARFileSizeException;
103    import com.liferay.portlet.exportimport.LARTypeException;
104    import com.liferay.portlet.exportimport.MissingReferenceException;
105    import com.liferay.portlet.exportimport.RemoteExportException;
106    import com.liferay.portlet.exportimport.backgroundtask.LayoutRemoteStagingBackgroundTaskExecutor;
107    import com.liferay.portlet.exportimport.backgroundtask.LayoutStagingBackgroundTaskExecutor;
108    import com.liferay.portlet.exportimport.backgroundtask.PortletStagingBackgroundTaskExecutor;
109    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationConstants;
110    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationParameterMapFactory;
111    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationSettingsMapFactory;
112    import com.liferay.portlet.exportimport.lar.ExportImportDateUtil;
113    import com.liferay.portlet.exportimport.lar.ExportImportHelperUtil;
114    import com.liferay.portlet.exportimport.lar.MissingReference;
115    import com.liferay.portlet.exportimport.lar.MissingReferences;
116    import com.liferay.portlet.exportimport.lar.PortletDataContext;
117    import com.liferay.portlet.exportimport.lar.PortletDataException;
118    import com.liferay.portlet.exportimport.lar.PortletDataHandlerKeys;
119    import com.liferay.portlet.exportimport.lar.StagedModelDataHandlerUtil;
120    import com.liferay.portlet.exportimport.lar.StagedModelType;
121    import com.liferay.portlet.exportimport.model.ExportImportConfiguration;
122    import com.liferay.portlet.exportimport.service.ExportImportConfigurationLocalServiceUtil;
123    import com.liferay.portlet.exportimport.service.StagingLocalServiceUtil;
124    
125    import java.io.Serializable;
126    
127    import java.util.ArrayList;
128    import java.util.Calendar;
129    import java.util.Date;
130    import java.util.HashMap;
131    import java.util.HashSet;
132    import java.util.Iterator;
133    import java.util.List;
134    import java.util.Locale;
135    import java.util.Map;
136    import java.util.Set;
137    
138    import javax.portlet.PortletPreferences;
139    import javax.portlet.PortletRequest;
140    
141    import javax.servlet.http.HttpServletRequest;
142    
143    /**
144     * @author Raymond Aug??
145     * @author Bruno Farache
146     * @author Wesley Gong
147     * @author Zsolt Balogh
148     */
149    @DoPrivileged
150    public class StagingImpl implements Staging {
151    
152            @Override
153            public String buildRemoteURL(
154                    String remoteAddress, int remotePort, String remotePathContext,
155                    boolean secureConnection, long remoteGroupId, boolean privateLayout) {
156    
157                    StringBundler sb = new StringBundler((remoteGroupId > 0) ? 4 : 9);
158    
159                    if (secureConnection) {
160                            sb.append(Http.HTTPS_WITH_SLASH);
161                    }
162                    else {
163                            sb.append(Http.HTTP_WITH_SLASH);
164                    }
165    
166                    sb.append(remoteAddress);
167    
168                    if (remotePort > 0) {
169                            sb.append(StringPool.COLON);
170                            sb.append(remotePort);
171                    }
172    
173                    if (Validator.isNotNull(remotePathContext)) {
174                            sb.append(remotePathContext);
175                    }
176    
177                    if (remoteGroupId > 0) {
178                            sb.append("/c/my_sites/view?");
179                            sb.append("groupId=");
180                            sb.append(remoteGroupId);
181                            sb.append("&privateLayout=");
182                            sb.append(privateLayout);
183                    }
184    
185                    return sb.toString();
186            }
187    
188            @Override
189            public String buildRemoteURL(UnicodeProperties typeSettingsProperties) {
190                    String remoteAddress = typeSettingsProperties.getProperty(
191                            "remoteAddress");
192                    int remotePort = GetterUtil.getInteger(
193                            typeSettingsProperties.getProperty("remotePort"));
194                    String remotePathContext = typeSettingsProperties.getProperty(
195                            "remotePathContext");
196                    boolean secureConnection = GetterUtil.getBoolean(
197                            typeSettingsProperties.getProperty("secureConnection"));
198    
199                    return buildRemoteURL(
200                            remoteAddress, remotePort, remotePathContext, secureConnection,
201                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
202            }
203    
204            /**
205             * @deprecated As of 7.0.0, replaced by {@link
206             *             StagingLocalServiceUtil#checkDefaultLayoutSetBranches(long,
207             *             Group, boolean, boolean, boolean, ServiceContext)}
208             */
209            @Deprecated
210            @Override
211            public void checkDefaultLayoutSetBranches(
212                            long userId, Group liveGroup, boolean branchingPublic,
213                            boolean branchingPrivate, boolean remote,
214                            ServiceContext serviceContext)
215                    throws PortalException {
216    
217                    StagingLocalServiceUtil.checkDefaultLayoutSetBranches(
218                            userId, liveGroup, branchingPublic, branchingPrivate, remote,
219                            serviceContext);
220            }
221    
222            @Override
223            public void copyFromLive(PortletRequest portletRequest)
224                    throws PortalException {
225    
226                    long stagingGroupId = ParamUtil.getLong(
227                            portletRequest, "stagingGroupId");
228    
229                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
230    
231                    long liveGroupId = stagingGroup.getLiveGroupId();
232    
233                    Map<String, String[]> parameterMap =
234                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
235                                    portletRequest);
236    
237                    publishLayouts(
238                            portletRequest, liveGroupId, stagingGroupId, parameterMap, false);
239            }
240    
241            @Override
242            public void copyFromLive(PortletRequest portletRequest, Portlet portlet)
243                    throws PortalException {
244    
245                    long plid = ParamUtil.getLong(portletRequest, "plid");
246    
247                    Layout targetLayout = LayoutLocalServiceUtil.getLayout(plid);
248    
249                    Group stagingGroup = targetLayout.getGroup();
250                    Group liveGroup = stagingGroup.getLiveGroup();
251    
252                    Layout sourceLayout = LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
253                            targetLayout.getUuid(), liveGroup.getGroupId(),
254                            targetLayout.isPrivateLayout());
255    
256                    copyPortlet(
257                            portletRequest, liveGroup.getGroupId(), stagingGroup.getGroupId(),
258                            sourceLayout.getPlid(), targetLayout.getPlid(),
259                            portlet.getPortletId());
260            }
261    
262            /**
263             * @deprecated As of 7.0.0, replaced by {@link #publishPortlet(long, long,
264             *             long, long, long, String, Map)}
265             */
266            @Deprecated
267            @Override
268            public void copyPortlet(
269                            PortletRequest portletRequest, long sourceGroupId,
270                            long targetGroupId, long sourcePlid, long targetPlid,
271                            String portletId)
272                    throws PortalException {
273    
274                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
275                            WebKeys.THEME_DISPLAY);
276    
277                    Map<String, String[]> parameterMap =
278                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
279                                    portletRequest);
280    
281                    publishPortlet(
282                            themeDisplay.getUserId(), sourceGroupId, targetGroupId, sourcePlid,
283                            targetPlid, portletId, parameterMap);
284            }
285    
286            @Override
287            public void copyRemoteLayouts(
288                            ExportImportConfiguration exportImportConfiguration)
289                    throws PortalException {
290    
291                    Map<String, Serializable> settingsMap =
292                            exportImportConfiguration.getSettingsMap();
293    
294                    long remoteGroupId = MapUtil.getLong(settingsMap, "remoteGroupId");
295                    String remoteAddress = MapUtil.getString(settingsMap, "remoteAddress");
296                    int remotePort = MapUtil.getInteger(settingsMap, "remotePort");
297                    String remotePathContext = MapUtil.getString(
298                            settingsMap, "remotePathContext");
299                    boolean secureConnection = MapUtil.getBoolean(
300                            settingsMap, "secureConnection");
301    
302                    validateRemoteGroup(
303                            exportImportConfiguration.getGroupId(), remoteGroupId,
304                            remoteAddress, remotePort, remotePathContext, secureConnection);
305    
306                    boolean remotePrivateLayout = MapUtil.getBoolean(
307                            settingsMap, "remotePrivateLayout");
308    
309                    doCopyRemoteLayouts(
310                            exportImportConfiguration, remoteAddress, remotePort,
311                            remotePathContext, secureConnection, remotePrivateLayout);
312            }
313    
314            @Override
315            public void copyRemoteLayouts(long exportImportConfigurationId)
316                    throws PortalException {
317    
318                    ExportImportConfiguration exportImportConfiguration =
319                            ExportImportConfigurationLocalServiceUtil.
320                                    getExportImportConfiguration(exportImportConfigurationId);
321    
322                    copyRemoteLayouts(exportImportConfiguration);
323            }
324    
325            @Override
326            public void copyRemoteLayouts(
327                            long sourceGroupId, boolean privateLayout,
328                            Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
329                            String remoteAddress, int remotePort, String remotePathContext,
330                            boolean secureConnection, long remoteGroupId,
331                            boolean remotePrivateLayout)
332                    throws PortalException {
333    
334                    validateRemoteGroup(
335                            sourceGroupId, remoteGroupId, remoteAddress, remotePort,
336                            remotePathContext, secureConnection);
337    
338                    PermissionChecker permissionChecker =
339                            PermissionThreadLocal.getPermissionChecker();
340    
341                    User user = permissionChecker.getUser();
342    
343                    Map<String, Serializable> settingsMap =
344                            ExportImportConfigurationSettingsMapFactory.buildSettingsMap(
345                                    user.getUserId(), sourceGroupId, privateLayout, layoutIdMap,
346                                    parameterMap, remoteAddress, remotePort, remotePathContext,
347                                    secureConnection, remoteGroupId, remotePrivateLayout,
348                                    user.getLocale(), user.getTimeZone());
349    
350                    ServiceContext serviceContext = new ServiceContext();
351    
352                    ExportImportConfiguration exportImportConfiguration =
353                            ExportImportConfigurationLocalServiceUtil.
354                                    addExportImportConfiguration(
355                                            user.getUserId(), sourceGroupId, StringPool.BLANK,
356                                            StringPool.BLANK, ExportImportConfigurationConstants.
357                                                    TYPE_PUBLISH_LAYOUT_REMOTE,
358                                            settingsMap, WorkflowConstants.STATUS_DRAFT,
359                                            serviceContext);
360    
361                    doCopyRemoteLayouts(
362                            exportImportConfiguration, remoteAddress, remotePort,
363                            remotePathContext, secureConnection, remotePrivateLayout);
364            }
365    
366            /**
367             * @deprecated As of 7.0.0, replaced by {@link #copyRemoteLayouts(long,
368             *             boolean, Map, Map, String, int, String, boolean, long,
369             *             boolean)}
370             */
371            @Deprecated
372            @Override
373            public void copyRemoteLayouts(
374                            long sourceGroupId, boolean privateLayout,
375                            Map<Long, Boolean> layoutIdMap, Map<String, String[]> parameterMap,
376                            String remoteAddress, int remotePort, String remotePathContext,
377                            boolean secureConnection, long remoteGroupId,
378                            boolean remotePrivateLayout, Date startDate, Date endDate)
379                    throws PortalException {
380    
381                    copyRemoteLayouts(
382                            sourceGroupId, privateLayout, layoutIdMap, parameterMap,
383                            remoteAddress, remotePort, remotePathContext, secureConnection,
384                            remoteGroupId, remotePrivateLayout);
385            }
386    
387            @Override
388            public void deleteLastImportSettings(Group liveGroup, boolean privateLayout)
389                    throws PortalException {
390    
391                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
392                            liveGroup.getGroupId(), privateLayout);
393    
394                    for (Layout layout : layouts) {
395                            UnicodeProperties typeSettingsProperties =
396                                    layout.getTypeSettingsProperties();
397    
398                            Set<String> keys = new HashSet<>();
399    
400                            for (String key : typeSettingsProperties.keySet()) {
401                                    if (key.startsWith("last-import-")) {
402                                            keys.add(key);
403                                    }
404                            }
405    
406                            if (keys.isEmpty()) {
407                                    continue;
408                            }
409    
410                            for (String key : keys) {
411                                    typeSettingsProperties.remove(key);
412                            }
413    
414                            LayoutLocalServiceUtil.updateLayout(
415                                    layout.getGroupId(), layout.getPrivateLayout(),
416                                    layout.getLayoutId(), typeSettingsProperties.toString());
417                    }
418            }
419    
420            @Override
421            public void deleteRecentLayoutRevisionId(
422                    HttpServletRequest request, long layoutSetBranchId, long plid) {
423    
424                    PortalPreferences portalPreferences =
425                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
426    
427                    deleteRecentLayoutRevisionId(
428                            portalPreferences, layoutSetBranchId, plid);
429            }
430    
431            @Override
432            public void deleteRecentLayoutRevisionId(
433                    long userId, long layoutSetBranchId, long plid) {
434    
435                    User user = UserLocalServiceUtil.fetchUser(userId);
436    
437                    PortalPreferences portalPreferences = null;
438    
439                    if (user != null) {
440                            portalPreferences = getPortalPreferences(user);
441                    }
442                    else {
443                            portalPreferences =
444                                    PortletPreferencesFactoryUtil.getPortalPreferences(
445                                            userId, false);
446                    }
447    
448                    deleteRecentLayoutRevisionId(
449                            portalPreferences, layoutSetBranchId, plid);
450            }
451    
452            /**
453             * @deprecated As of 7.0.0, replaced by {@link
454             *             #deleteRecentLayoutRevisionId(long, long, long)}
455             */
456            @Deprecated
457            @Override
458            public void deleteRecentLayoutRevisionId(
459                    User user, long layoutSetBranchId, long plid) {
460    
461                    PortalPreferences portalPreferences = getPortalPreferences(user);
462    
463                    deleteRecentLayoutRevisionId(
464                            portalPreferences, layoutSetBranchId, plid);
465            }
466    
467            /**
468             * @deprecated As of 6.2.0, replaced by {@link
469             *             com.liferay.portlet.exportimport.service.StagingLocalService#disableStaging(
470             *             Group, ServiceContext)}
471             */
472            @Deprecated
473            @Override
474            public void disableStaging(
475                            Group scopeGroup, Group liveGroup, ServiceContext serviceContext)
476                    throws Exception {
477    
478                    disableStaging((PortletRequest)null, liveGroup, serviceContext);
479            }
480    
481            /**
482             * @deprecated As of 6.2.0, replaced by {@link
483             *             com.liferay.portlet.exportimport.service.StagingLocalService#disableStaging(
484             *             Group, ServiceContext)}
485             */
486            @Deprecated
487            @Override
488            public void disableStaging(Group liveGroup, ServiceContext serviceContext)
489                    throws Exception {
490    
491                    disableStaging((PortletRequest)null, liveGroup, serviceContext);
492            }
493    
494            /**
495             * @deprecated As of 6.2.0, replaced by {@link
496             *             com.liferay.portlet.exportimport.service.StagingLocalService#disableStaging(
497             *             PortletRequest, Group, ServiceContext)}
498             */
499            @Deprecated
500            @Override
501            public void disableStaging(
502                            PortletRequest portletRequest, Group scopeGroup, Group liveGroup,
503                            ServiceContext serviceContext)
504                    throws Exception {
505    
506                    disableStaging(portletRequest, liveGroup, serviceContext);
507            }
508    
509            /**
510             * @deprecated As of 6.2.0, replaced by {@link
511             *             com.liferay.portlet.exportimport.service.StagingLocalService#disableStaging(
512             *             PortletRequest, Group, ServiceContext)}
513             */
514            @Deprecated
515            @Override
516            public void disableStaging(
517                            PortletRequest portletRequest, Group liveGroup,
518                            ServiceContext serviceContext)
519                    throws Exception {
520    
521                    StagingLocalServiceUtil.disableStaging(
522                            portletRequest, liveGroup, serviceContext);
523            }
524    
525            /**
526             * @deprecated As of 6.2.0, replaced by {@link
527             *             com.liferay.portlet.exportimport.service.StagingLocalService#enableLocalStaging(
528             *             long, Group, boolean, boolean, ServiceContext)}
529             */
530            @Deprecated
531            @Override
532            public void enableLocalStaging(
533                            long userId, Group scopeGroup, Group liveGroup,
534                            boolean branchingPublic, boolean branchingPrivate,
535                            ServiceContext serviceContext)
536                    throws Exception {
537    
538                    StagingLocalServiceUtil.enableLocalStaging(
539                            userId, liveGroup, branchingPublic, branchingPrivate,
540                            serviceContext);
541            }
542    
543            /**
544             * @deprecated As of 6.2.0, replaced by {@link
545             *             com.liferay.portlet.exportimport.service.StagingLocalService#enableRemoteStaging(
546             *             long, Group, boolean, boolean, String, int, String, boolean,
547             *             long, ServiceContext)}
548             */
549            @Deprecated
550            @Override
551            public void enableRemoteStaging(
552                            long userId, Group scopeGroup, Group liveGroup,
553                            boolean branchingPublic, boolean branchingPrivate,
554                            String remoteAddress, int remotePort, String remotePathContext,
555                            boolean secureConnection, long remoteGroupId,
556                            ServiceContext serviceContext)
557                    throws Exception {
558    
559                    StagingLocalServiceUtil.enableRemoteStaging(
560                            userId, liveGroup, branchingPublic, branchingPrivate, remoteAddress,
561                            remotePort, remotePathContext, secureConnection, remoteGroupId,
562                            serviceContext);
563            }
564    
565            @Override
566            public JSONArray getErrorMessagesJSONArray(
567                    Locale locale, Map<String, MissingReference> missingReferences,
568                    Map<String, Serializable> contextMap) {
569    
570                    JSONArray errorMessagesJSONArray = JSONFactoryUtil.createJSONArray();
571    
572                    for (String missingReferenceDisplayName : missingReferences.keySet()) {
573                            MissingReference missingReference = missingReferences.get(
574                                    missingReferenceDisplayName);
575    
576                            JSONObject errorMessageJSONObject =
577                                    JSONFactoryUtil.createJSONObject();
578    
579                            String className = missingReference.getClassName();
580                            Map<String, String> referrers = missingReference.getReferrers();
581    
582                            if (className.equals(StagedTheme.class.getName())) {
583                                    errorMessageJSONObject.put(
584                                            "info",
585                                            LanguageUtil.format(
586                                                    locale,
587                                                    "the-referenced-theme-x-is-not-deployed-in-the-" +
588                                                            "current-environment",
589                                                    missingReference.getClassPK(), false));
590                            }
591                            else if (referrers.size() == 1) {
592                                    Set<Map.Entry<String, String>> referrerDisplayNames =
593                                            referrers.entrySet();
594    
595                                    Iterator<Map.Entry<String, String>> iterator =
596                                            referrerDisplayNames.iterator();
597    
598                                    Map.Entry<String, String> entry = iterator.next();
599    
600                                    String referrerDisplayName = entry.getKey();
601                                    String referrerClassName = entry.getValue();
602    
603                                    if (referrerClassName.equals(Portlet.class.getName())) {
604                                            referrerDisplayName = PortalUtil.getPortletTitle(
605                                                    referrerDisplayName, locale);
606                                    }
607    
608                                    errorMessageJSONObject.put(
609                                            "info",
610                                            LanguageUtil.format(
611                                                    locale, "referenced-by-a-x-x",
612                                                    new String[] {
613                                                            ResourceActionsUtil.getModelResource(
614                                                                    locale, referrerClassName),
615                                                            referrerDisplayName
616                                                    }, false));
617                            }
618                            else {
619                                    errorMessageJSONObject.put(
620                                            "info",
621                                            LanguageUtil.format(
622                                                    locale, "referenced-by-x-elements", referrers.size(),
623                                                    true));
624                            }
625    
626                            errorMessageJSONObject.put("name", missingReferenceDisplayName);
627    
628                            Group group = GroupLocalServiceUtil.fetchGroup(
629                                    missingReference.getGroupId());
630    
631                            if (group != null) {
632                                    errorMessageJSONObject.put(
633                                            "site",
634                                            LanguageUtil.format(
635                                                    locale, "in-site-x", missingReference.getGroupId(),
636                                                    false));
637                            }
638    
639                            errorMessageJSONObject.put(
640                                    "type",
641                                    ResourceActionsUtil.getModelResource(
642                                            locale, missingReference.getClassName()));
643    
644                            errorMessagesJSONArray.put(errorMessageJSONObject);
645                    }
646    
647                    return errorMessagesJSONArray;
648            }
649    
650            @Override
651            public JSONObject getExceptionMessagesJSONObject(
652                    Locale locale, Exception e, Map<String, Serializable> contextMap) {
653    
654                    String cmd = null;
655    
656                    if (contextMap != null) {
657                            cmd = (String)contextMap.get(Constants.CMD);
658                    }
659    
660                    JSONObject exceptionMessagesJSONObject =
661                            JSONFactoryUtil.createJSONObject();
662    
663                    String errorMessage = StringPool.BLANK;
664                    JSONArray errorMessagesJSONArray = null;
665                    int errorType = 0;
666                    JSONArray warningMessagesJSONArray = null;
667    
668                    if (e instanceof DuplicateFileException) {
669                            errorMessage = LanguageUtil.get(
670                                    locale, "please-enter-a-unique-document-name");
671                            errorType = ServletResponseConstants.SC_DUPLICATE_FILE_EXCEPTION;
672                    }
673                    else if (e instanceof FileExtensionException) {
674                            errorMessage = LanguageUtil.format(
675                                    locale,
676                                    "document-names-must-end-with-one-of-the-following-extensions",
677                                    ".lar", false);
678                            errorType = ServletResponseConstants.SC_FILE_EXTENSION_EXCEPTION;
679                    }
680                    else if (e instanceof FileNameException) {
681                            errorMessage = LanguageUtil.get(
682                                    locale, "please-enter-a-file-with-a-valid-file-name");
683                            errorType = ServletResponseConstants.SC_FILE_NAME_EXCEPTION;
684                    }
685                    else if (e instanceof FileSizeException ||
686                                     e instanceof LARFileSizeException) {
687    
688                            long fileMaxSize = PropsValues.DL_FILE_MAX_SIZE;
689    
690                            try {
691                                    fileMaxSize = PrefsPropsUtil.getLong(
692                                            PropsKeys.DL_FILE_MAX_SIZE);
693    
694                                    if (fileMaxSize == 0) {
695                                            fileMaxSize = PrefsPropsUtil.getLong(
696                                                    PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_MAX_SIZE);
697                                    }
698                            }
699                            catch (Exception e1) {
700                            }
701    
702                            if (Validator.equals(cmd, Constants.PUBLISH_TO_LIVE) ||
703                                    Validator.equals(cmd, Constants.PUBLISH_TO_REMOTE)) {
704    
705                                    errorMessage = LanguageUtil.get(
706                                            locale,
707                                            "file-size-limit-exceeded.-please-ensure-that-the-file-" +
708                                                    "does-not-exceed-the-file-size-limit-in-both-the-" +
709                                                            "live-environment-and-the-staging-environment");
710                            }
711                            else {
712                                    errorMessage = LanguageUtil.format(
713                                            locale,
714                                            "please-enter-a-file-with-a-valid-file-size-no-larger-" +
715                                                    "than-x",
716                                            TextFormatter.formatStorageSize(fileMaxSize, locale),
717                                            false);
718                            }
719    
720                            errorType = ServletResponseConstants.SC_FILE_SIZE_EXCEPTION;
721                    }
722                    else if (e instanceof LARTypeException) {
723                            LARTypeException lte = (LARTypeException)e;
724    
725                            errorMessage = LanguageUtil.format(
726                                    locale,
727                                    "please-import-a-lar-file-of-the-correct-type-x-is-not-valid",
728                                    lte.getMessage());
729                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
730                    }
731                    else if (e instanceof LARFileException) {
732                            errorMessage = LanguageUtil.get(
733                                    locale, "please-specify-a-lar-file-to-import");
734                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
735                    }
736                    else if (e instanceof LayoutPrototypeException) {
737                            LayoutPrototypeException lpe = (LayoutPrototypeException)e;
738    
739                            StringBundler sb = new StringBundler(4);
740    
741                            sb.append("the-lar-file-could-not-be-imported-because-it-");
742                            sb.append("requires-page-templates-or-site-templates-that-could-");
743                            sb.append("not-be-found.-please-import-the-following-templates-");
744                            sb.append("manually");
745    
746                            errorMessage = LanguageUtil.get(locale, sb.toString());
747    
748                            errorMessagesJSONArray = JSONFactoryUtil.createJSONArray();
749    
750                            List<Tuple> missingLayoutPrototypes =
751                                    lpe.getMissingLayoutPrototypes();
752    
753                            for (Tuple missingLayoutPrototype : missingLayoutPrototypes) {
754                                    JSONObject errorMessageJSONObject =
755                                            JSONFactoryUtil.createJSONObject();
756    
757                                    String layoutPrototypeUuid =
758                                            (String)missingLayoutPrototype.getObject(1);
759    
760                                    errorMessageJSONObject.put("info", layoutPrototypeUuid);
761    
762                                    String layoutPrototypeName =
763                                            (String)missingLayoutPrototype.getObject(2);
764    
765                                    errorMessageJSONObject.put("name", layoutPrototypeName);
766    
767                                    String layoutPrototypeClassName =
768                                            (String)missingLayoutPrototype.getObject(0);
769    
770                                    errorMessageJSONObject.put(
771                                            "type",
772                                            ResourceActionsUtil.getModelResource(
773                                                    locale, layoutPrototypeClassName));
774    
775                                    errorMessagesJSONArray.put(errorMessageJSONObject);
776                            }
777    
778                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
779                    }
780                    else if (e instanceof LocaleException) {
781                            LocaleException le = (LocaleException)e;
782    
783                            errorMessage = LanguageUtil.format(
784                                    locale,
785                                    "the-available-languages-in-the-lar-file-x-do-not-match-the-" +
786                                            "site's-available-languages-x",
787                                    new String[] {
788                                            StringUtil.merge(
789                                                    le.getSourceAvailableLocales(),
790                                                    StringPool.COMMA_AND_SPACE),
791                                            StringUtil.merge(
792                                                    le.getTargetAvailableLocales(),
793                                                    StringPool.COMMA_AND_SPACE)
794                                    }, false);
795    
796                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
797                    }
798                    else if (e instanceof MissingReferenceException) {
799                            MissingReferenceException mre = (MissingReferenceException)e;
800    
801                            if (Validator.equals(cmd, Constants.PUBLISH_TO_LIVE) ||
802                                    Validator.equals(cmd, Constants.PUBLISH_TO_REMOTE)) {
803    
804                                    errorMessage = LanguageUtil.get(
805                                            locale,
806                                            "there-are-missing-references-that-could-not-be-found-in-" +
807                                                    "the-live-environment");
808                            }
809                            else {
810                                    errorMessage = LanguageUtil.get(
811                                            locale,
812                                            "there-are-missing-references-that-could-not-be-found-in-" +
813                                                    "the-current-site");
814                            }
815    
816                            MissingReferences missingReferences = mre.getMissingReferences();
817    
818                            errorMessagesJSONArray = getErrorMessagesJSONArray(
819                                    locale, missingReferences.getDependencyMissingReferences(),
820                                    contextMap);
821                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
822                            warningMessagesJSONArray = getWarningMessagesJSONArray(
823                                    locale, missingReferences.getWeakMissingReferences(),
824                                    contextMap);
825                    }
826                    else if (e instanceof PortletDataException) {
827                            PortletDataException pde = (PortletDataException)e;
828    
829                            StagedModel stagedModel = pde.getStagedModel();
830    
831                            String referrerClassName = StringPool.BLANK;
832                            String referrerDisplayName = StringPool.BLANK;
833    
834                            if (stagedModel != null) {
835                                    StagedModelType stagedModelType =
836                                            stagedModel.getStagedModelType();
837    
838                                    referrerClassName = stagedModelType.getClassName();
839                                    referrerDisplayName = StagedModelDataHandlerUtil.getDisplayName(
840                                            stagedModel);
841                            }
842    
843                            if (pde.getType() == PortletDataException.INVALID_GROUP) {
844                                    errorMessage = LanguageUtil.format(
845                                            locale,
846                                            "the-x-x-could-not-be-exported-because-it-is-not-in-the-" +
847                                                    "currently-exported-group",
848                                            new String[] {
849                                                    ResourceActionsUtil.getModelResource(
850                                                            locale, referrerClassName),
851                                                    referrerDisplayName
852                                            }, false);
853                            }
854                            else if (pde.getType() == PortletDataException.MISSING_DEPENDENCY) {
855                                    errorMessage = LanguageUtil.format(
856                                            locale,
857                                            "the-x-x-has-missing-references-that-could-not-be-found-" +
858                                                    "during-the-export",
859                                            new String[] {
860                                                    ResourceActionsUtil.getModelResource(
861                                                            locale, referrerClassName),
862                                                    referrerDisplayName
863                                            }, false);
864                            }
865                            else if (pde.getType() == PortletDataException.STATUS_IN_TRASH) {
866                                    errorMessage = LanguageUtil.format(
867                                            locale,
868                                            "the-x-x-could-not-be-exported-because-it-is-in-the-" +
869                                                    "recycle-bin",
870                                            new String[] {
871                                                    ResourceActionsUtil.getModelResource(
872                                                            locale, referrerClassName),
873                                                    referrerDisplayName
874                                            }, false);
875                            }
876                            else if (pde.getType() == PortletDataException.STATUS_UNAVAILABLE) {
877                                    errorMessage = LanguageUtil.format(
878                                            locale,
879                                            "the-x-x-could-not-be-exported-because-its-workflow-" +
880                                                    "status-is-not-exportable",
881                                            new String[] {
882                                                    ResourceActionsUtil.getModelResource(
883                                                            locale, referrerClassName),
884                                                    referrerDisplayName
885                                            }, false);
886                            }
887                            else {
888                                    errorMessage = e.getLocalizedMessage();
889                            }
890    
891                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
892                    }
893                    else if (e instanceof PortletIdException) {
894                            errorMessage = LanguageUtil.get(
895                                    locale, "please-import-a-lar-file-for-the-current-portlet");
896                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
897                    }
898                    else {
899                            errorMessage = e.getLocalizedMessage();
900                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
901                    }
902    
903                    exceptionMessagesJSONObject.put("message", errorMessage);
904    
905                    if ((errorMessagesJSONArray != null) &&
906                            (errorMessagesJSONArray.length() > 0)) {
907    
908                            exceptionMessagesJSONObject.put(
909                                    "messageListItems", errorMessagesJSONArray);
910                    }
911    
912                    exceptionMessagesJSONObject.put("status", errorType);
913    
914                    if ((warningMessagesJSONArray != null) &&
915                            (warningMessagesJSONArray.length() > 0)) {
916    
917                            exceptionMessagesJSONObject.put(
918                                    "warningMessages", warningMessagesJSONArray);
919                    }
920    
921                    return exceptionMessagesJSONObject;
922            }
923    
924            @Override
925            public Group getLiveGroup(long groupId) {
926                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
927    
928                    if (group == null) {
929                            return null;
930                    }
931    
932                    if (!group.isStagedRemotely() && group.isStagingGroup()) {
933                            return group.getLiveGroup();
934                    }
935    
936                    return group;
937            }
938    
939            @Override
940            public long getLiveGroupId(long groupId) {
941                    Group group = getLiveGroup(groupId);
942    
943                    if (group == null) {
944                            return groupId;
945                    }
946    
947                    return group.getGroupId();
948            }
949    
950            /**
951             * @deprecated As of 7.0.0, moved to {@link
952             *             ExportImportHelperUtil#getMissingParentLayouts(Layout, long)}
953             */
954            @Deprecated
955            @Override
956            public List<Layout> getMissingParentLayouts(Layout layout, long liveGroupId)
957                    throws PortalException {
958    
959                    return ExportImportHelperUtil.getMissingParentLayouts(
960                            layout, liveGroupId);
961            }
962    
963            @Override
964            public long getRecentLayoutRevisionId(
965                            HttpServletRequest request, long layoutSetBranchId, long plid)
966                    throws PortalException {
967    
968                    PortalPreferences portalPreferences =
969                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
970    
971                    return getRecentLayoutRevisionId(
972                            portalPreferences, layoutSetBranchId, plid);
973            }
974    
975            @Override
976            public long getRecentLayoutRevisionId(
977                            User user, long layoutSetBranchId, long plid)
978                    throws PortalException {
979    
980                    PortalPreferences portalPreferences = getPortalPreferences(user);
981    
982                    return getRecentLayoutRevisionId(
983                            portalPreferences, layoutSetBranchId, plid);
984            }
985    
986            @Override
987            public long getRecentLayoutSetBranchId(
988                    HttpServletRequest request, long layoutSetId) {
989    
990                    return GetterUtil.getLong(
991                            SessionClicks.get(
992                                    request, Staging.class.getName(),
993                                    getRecentLayoutSetBranchIdKey(layoutSetId)));
994            }
995    
996            @Override
997            public long getRecentLayoutSetBranchId(User user, long layoutSetId) {
998                    PortalPreferences portalPreferences = getPortalPreferences(user);
999    
1000                    try {
1001                            return getRecentLayoutAttribute(
1002                                    portalPreferences, getRecentLayoutSetBranchIdKey(layoutSetId));
1003                    }
1004                    catch (JSONException jsone) {
1005                            if (_log.isWarnEnabled()) {
1006                                    _log.warn(
1007                                            "Unable to get recent layout set branch ID with user " +
1008                                                    user.getUserId() + " and layout set " + layoutSetId,
1009                                            jsone);
1010                            }
1011                    }
1012    
1013                    return 0;
1014            }
1015    
1016            @Override
1017            public String getSchedulerGroupName(String destinationName, long groupId) {
1018                    return destinationName.concat(StringPool.SLASH).concat(
1019                            String.valueOf(groupId));
1020            }
1021    
1022            @Override
1023            public String getStagedPortletId(String portletId) {
1024                    String key = portletId;
1025    
1026                    if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
1027                            return key;
1028                    }
1029    
1030                    return StagingConstants.STAGED_PORTLET.concat(portletId);
1031            }
1032    
1033            @Override
1034            public Group getStagingGroup(long groupId) {
1035                    Group group = GroupLocalServiceUtil.fetchGroup(groupId);
1036    
1037                    if (group == null) {
1038                            return null;
1039                    }
1040    
1041                    Group stagingGroup = group;
1042    
1043                    if (!group.isStagedRemotely() && group.hasStagingGroup()) {
1044                            stagingGroup = group.getStagingGroup();
1045                    }
1046    
1047                    return stagingGroup;
1048            }
1049    
1050            /**
1051             * @deprecated As of 7.0.0, replaced by {@link
1052             *             ExportImportConfigurationParameterMapFactory#buildParameterMap(
1053             *             )}
1054             */
1055            @Deprecated
1056            @Override
1057            public Map<String, String[]> getStagingParameters() {
1058                    return ExportImportConfigurationParameterMapFactory.buildParameterMap();
1059            }
1060    
1061            /**
1062             * @deprecated As of 7.0.0, replaced by {@link
1063             *             ExportImportConfigurationParameterMapFactory#buildParameterMap(
1064             *             PortletRequest)}
1065             */
1066            @Deprecated
1067            @Override
1068            public Map<String, String[]> getStagingParameters(
1069                    PortletRequest portletRequest) {
1070    
1071                    return ExportImportConfigurationParameterMapFactory.buildParameterMap(
1072                            portletRequest);
1073            }
1074    
1075            @Override
1076            public JSONArray getWarningMessagesJSONArray(
1077                    Locale locale, Map<String, MissingReference> missingReferences,
1078                    Map<String, Serializable> contextMap) {
1079    
1080                    JSONArray warningMessagesJSONArray = JSONFactoryUtil.createJSONArray();
1081    
1082                    for (String missingReferenceReferrerClassName :
1083                                    missingReferences.keySet()) {
1084    
1085                            MissingReference missingReference = missingReferences.get(
1086                                    missingReferenceReferrerClassName);
1087    
1088                            Map<String, String> referrers = missingReference.getReferrers();
1089    
1090                            JSONObject errorMessageJSONObject =
1091                                    JSONFactoryUtil.createJSONObject();
1092    
1093                            if (Validator.isNotNull(missingReference.getClassName())) {
1094                                    errorMessageJSONObject.put(
1095                                            "info",
1096                                            LanguageUtil.format(
1097                                                    locale,
1098                                                    "the-original-x-does-not-exist-in-the-current-" +
1099                                                            "environment",
1100                                                    ResourceActionsUtil.getModelResource(
1101                                                            locale, missingReference.getClassName()),
1102                                                    false));
1103                            }
1104    
1105                            errorMessageJSONObject.put("size", referrers.size());
1106                            errorMessageJSONObject.put(
1107                                    "type",
1108                                    ResourceActionsUtil.getModelResource(
1109                                            locale, missingReferenceReferrerClassName));
1110    
1111                            warningMessagesJSONArray.put(errorMessageJSONObject);
1112                    }
1113    
1114                    return warningMessagesJSONArray;
1115            }
1116    
1117            @Override
1118            public WorkflowTask getWorkflowTask(
1119                            long userId, LayoutRevision layoutRevision)
1120                    throws PortalException {
1121    
1122                    WorkflowInstanceLink workflowInstanceLink =
1123                            WorkflowInstanceLinkLocalServiceUtil.fetchWorkflowInstanceLink(
1124                                    layoutRevision.getCompanyId(), layoutRevision.getGroupId(),
1125                                    LayoutRevision.class.getName(),
1126                                    layoutRevision.getLayoutRevisionId());
1127    
1128                    if (workflowInstanceLink == null) {
1129                            return null;
1130                    }
1131    
1132                    List<WorkflowTask> workflowTasks =
1133                            WorkflowTaskManagerUtil.getWorkflowTasksByWorkflowInstance(
1134                                    layoutRevision.getCompanyId(), userId,
1135                                    workflowInstanceLink.getWorkflowInstanceId(), false, 0, 1,
1136                                    null);
1137    
1138                    if (!workflowTasks.isEmpty()) {
1139                            return workflowTasks.get(0);
1140                    }
1141    
1142                    return null;
1143            }
1144    
1145            @Override
1146            public boolean hasWorkflowTask(long userId, LayoutRevision layoutRevision)
1147                    throws PortalException {
1148    
1149                    WorkflowTask workflowTask = getWorkflowTask(userId, layoutRevision);
1150    
1151                    if (workflowTask != null) {
1152                            return true;
1153                    }
1154    
1155                    return false;
1156            }
1157    
1158            @Override
1159            public boolean isIncomplete(Layout layout, long layoutSetBranchId) {
1160                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
1161                            layout);
1162    
1163                    if (layoutRevision == null) {
1164                            try {
1165                                    layoutRevision =
1166                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
1167                                                    layoutSetBranchId, layout.getPlid(), true);
1168    
1169                                    return false;
1170                            }
1171                            catch (Exception e) {
1172                            }
1173                    }
1174    
1175                    try {
1176                            layoutRevision = LayoutRevisionLocalServiceUtil.getLayoutRevision(
1177                                    layoutSetBranchId, layout.getPlid(), false);
1178                    }
1179                    catch (Exception e) {
1180                    }
1181    
1182                    if ((layoutRevision == null) ||
1183                            (layoutRevision.getStatus() ==
1184                                    WorkflowConstants.STATUS_INCOMPLETE)) {
1185    
1186                            return true;
1187                    }
1188    
1189                    return false;
1190            }
1191    
1192            /**
1193             * @deprecated As of 7.0.0, see {@link
1194             *             com.liferay.portal.kernel.backgroundtask.BackgroundTaskExecutor#getIsolationLevel(
1195             *             )}
1196             */
1197            @Deprecated
1198            @Override
1199            public void lockGroup(long userId, long groupId) throws PortalException {
1200                    if (LockManagerUtil.isLocked(Staging.class.getName(), groupId)) {
1201                            Lock lock = LockManagerUtil.getLock(
1202                                    Staging.class.getName(), groupId);
1203    
1204                            throw new DuplicateLockException(lock);
1205                    }
1206    
1207                    LockManagerUtil.lock(
1208                            userId, Staging.class.getName(), String.valueOf(groupId),
1209                            StagingImpl.class.getName(), false,
1210                            StagingConstants.LOCK_EXPIRATION_TIME);
1211            }
1212    
1213            @Override
1214            public void publishLayout(
1215                            long userId, long plid, long liveGroupId, boolean includeChildren)
1216                    throws PortalException {
1217    
1218                    Map<String, String[]> parameterMap =
1219                            ExportImportConfigurationParameterMapFactory.buildParameterMap();
1220    
1221                    parameterMap.put(
1222                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1223                            new String[] {Boolean.FALSE.toString()});
1224    
1225                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1226    
1227                    List<Layout> layouts = new ArrayList<>();
1228    
1229                    layouts.add(layout);
1230    
1231                    List<Layout> parentLayouts =
1232                            ExportImportHelperUtil.getMissingParentLayouts(layout, liveGroupId);
1233    
1234                    layouts.addAll(parentLayouts);
1235    
1236                    if (includeChildren) {
1237                            layouts.addAll(layout.getAllChildren());
1238                    }
1239    
1240                    long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);
1241    
1242                    publishLayouts(
1243                            userId, layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
1244                            layoutIds, parameterMap);
1245            }
1246    
1247            @Override
1248            public void publishLayouts(
1249                            long userId, ExportImportConfiguration exportImportConfiguration)
1250                    throws PortalException {
1251    
1252                    Map<String, Serializable> taskContextMap = new HashMap<>();
1253    
1254                    taskContextMap.put(Constants.CMD, Constants.PUBLISH_TO_LIVE);
1255                    taskContextMap.put(
1256                            "exportImportConfigurationId",
1257                            exportImportConfiguration.getExportImportConfigurationId());
1258    
1259                    BackgroundTaskLocalServiceUtil.addBackgroundTask(
1260                            userId, exportImportConfiguration.getGroupId(), StringPool.BLANK,
1261                            null, LayoutStagingBackgroundTaskExecutor.class, taskContextMap,
1262                            new ServiceContext());
1263            }
1264    
1265            @Override
1266            public void publishLayouts(long userId, long exportImportConfigurationId)
1267                    throws PortalException {
1268    
1269                    ExportImportConfiguration exportImportConfiguration =
1270                            ExportImportConfigurationLocalServiceUtil.
1271                                    getExportImportConfiguration(exportImportConfigurationId);
1272    
1273                    publishLayouts(userId, exportImportConfiguration);
1274            }
1275    
1276            @Override
1277            public void publishLayouts(
1278                            long userId, long sourceGroupId, long targetGroupId,
1279                            boolean privateLayout, long[] layoutIds,
1280                            Map<String, String[]> parameterMap)
1281                    throws PortalException {
1282    
1283                    parameterMap.put(
1284                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
1285                            new String[] {Boolean.TRUE.toString()});
1286    
1287                    User user = UserLocalServiceUtil.getUser(userId);
1288    
1289                    Map<String, Serializable> settingsMap =
1290                            ExportImportConfigurationSettingsMapFactory.buildSettingsMap(
1291                                    userId, sourceGroupId, targetGroupId, privateLayout, layoutIds,
1292                                    parameterMap, user.getLocale(), user.getTimeZone());
1293    
1294                    ExportImportConfiguration exportImportConfiguration =
1295                            ExportImportConfigurationLocalServiceUtil.
1296                                    addExportImportConfiguration(
1297                                            userId, sourceGroupId, StringPool.BLANK, StringPool.BLANK,
1298                                            ExportImportConfigurationConstants.
1299                                                    TYPE_PUBLISH_LAYOUT_LOCAL,
1300                                            settingsMap, WorkflowConstants.STATUS_DRAFT,
1301                                            new ServiceContext());
1302    
1303                    publishLayouts(userId, exportImportConfiguration);
1304            }
1305    
1306            /**
1307             * @deprecated As of 7.0.0, replaced by {@link #publishLayouts(long, long,
1308             *             long, boolean, long[], Map)}
1309             */
1310            @Deprecated
1311            @Override
1312            public void publishLayouts(
1313                            long userId, long sourceGroupId, long targetGroupId,
1314                            boolean privateLayout, long[] layoutIds,
1315                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1316                    throws PortalException {
1317    
1318                    publishLayouts(
1319                            userId, sourceGroupId, targetGroupId, privateLayout, layoutIds,
1320                            parameterMap);
1321            }
1322    
1323            /**
1324             * @deprecated As of 7.0.0, replaced by {@link #publishLayouts(long, long,
1325             *             long, boolean, long[], Map)}
1326             */
1327            @Deprecated
1328            @Override
1329            public void publishLayouts(
1330                            long userId, long sourceGroupId, long targetGroupId,
1331                            boolean privateLayout, Map<Long, Boolean> layoutIdMap,
1332                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1333                    throws PortalException {
1334    
1335                    publishLayouts(
1336                            userId, sourceGroupId, targetGroupId, privateLayout,
1337                            ExportImportHelperUtil.getLayoutIds(layoutIdMap, targetGroupId),
1338                            parameterMap, startDate, endDate);
1339            }
1340    
1341            @Override
1342            public void publishLayouts(
1343                            long userId, long sourceGroupId, long targetGroupId,
1344                            boolean privateLayout, Map<String, String[]> parameterMap)
1345                    throws PortalException {
1346    
1347                    List<Layout> sourceGroupLayouts = LayoutLocalServiceUtil.getLayouts(
1348                            sourceGroupId, privateLayout);
1349    
1350                    publishLayouts(
1351                            userId, sourceGroupId, targetGroupId, privateLayout,
1352                            ExportImportHelperUtil.getLayoutIds(sourceGroupLayouts),
1353                            parameterMap);
1354            }
1355    
1356            /**
1357             * @deprecated As of 7.0.0, replaced by {@link #publishLayouts(long, long,
1358             *             long, boolean, Map)}
1359             */
1360            @Deprecated
1361            @Override
1362            public void publishLayouts(
1363                            long userId, long sourceGroupId, long targetGroupId,
1364                            boolean privateLayout, Map<String, String[]> parameterMap,
1365                            Date startDate, Date endDate)
1366                    throws PortalException {
1367    
1368                    publishLayouts(
1369                            userId, sourceGroupId, targetGroupId, privateLayout, parameterMap);
1370            }
1371    
1372            @Override
1373            public void publishPortlet(
1374                            long userId, ExportImportConfiguration exportImportConfiguration)
1375                    throws PortalException {
1376    
1377                    Map<String, Serializable> taskContextMap = new HashMap<>();
1378    
1379                    taskContextMap.put(Constants.CMD, Constants.PUBLISH_TO_LIVE);
1380                    taskContextMap.put(
1381                            "exportImportConfigurationId",
1382                            exportImportConfiguration.getExportImportConfigurationId());
1383    
1384                    BackgroundTaskLocalServiceUtil.addBackgroundTask(
1385                            userId, exportImportConfiguration.getGroupId(),
1386                            exportImportConfiguration.getName(), null,
1387                            PortletStagingBackgroundTaskExecutor.class, taskContextMap,
1388                            new ServiceContext());
1389            }
1390    
1391            @Override
1392            public void publishPortlet(long userId, long exportImportConfigurationId)
1393                    throws PortalException {
1394    
1395                    ExportImportConfiguration exportImportConfiguration =
1396                            ExportImportConfigurationLocalServiceUtil.
1397                                    getExportImportConfiguration(exportImportConfigurationId);
1398    
1399                    publishPortlet(userId, exportImportConfiguration);
1400            }
1401    
1402            @Override
1403            public void publishPortlet(
1404                            long userId, long sourceGroupId, long targetGroupId,
1405                            long sourcePlid, long targetPlid, String portletId,
1406                            Map<String, String[]> parameterMap)
1407                    throws PortalException {
1408    
1409                    User user = UserLocalServiceUtil.getUser(userId);
1410    
1411                    Map<String, Serializable> settingsMap =
1412                            ExportImportConfigurationSettingsMapFactory.buildSettingsMap(
1413                                    userId, sourceGroupId, sourcePlid, targetGroupId, targetPlid,
1414                                    portletId, parameterMap, Constants.PUBLISH_TO_LIVE,
1415                                    user.getLocale(), user.getTimeZone());
1416    
1417                    ServiceContext serviceContext = new ServiceContext();
1418    
1419                    ExportImportConfiguration exportImportConfiguration =
1420                            ExportImportConfigurationLocalServiceUtil.
1421                                    addExportImportConfiguration(
1422                                            userId, sourceGroupId, portletId, StringPool.BLANK,
1423                                            ExportImportConfigurationConstants.TYPE_PUBLISH_PORTLET,
1424                                            settingsMap, WorkflowConstants.STATUS_DRAFT,
1425                                            serviceContext);
1426    
1427                    publishPortlet(userId, exportImportConfiguration);
1428            }
1429    
1430            @Override
1431            public void publishToLive(PortletRequest portletRequest)
1432                    throws PortalException {
1433    
1434                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1435    
1436                    Group liveGroup = getLiveGroup(groupId);
1437    
1438                    Map<String, String[]> parameterMap =
1439                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
1440                                    portletRequest);
1441    
1442                    if (liveGroup.isStaged()) {
1443                            if (liveGroup.isStagedRemotely()) {
1444                                    publishToRemote(portletRequest);
1445                            }
1446                            else {
1447                                    Group stagingGroup = liveGroup.getStagingGroup();
1448    
1449                                    publishLayouts(
1450                                            portletRequest, stagingGroup.getGroupId(),
1451                                            liveGroup.getGroupId(), parameterMap, false);
1452                            }
1453                    }
1454            }
1455    
1456            @Override
1457            public void publishToLive(PortletRequest portletRequest, Portlet portlet)
1458                    throws PortalException {
1459    
1460                    long plid = ParamUtil.getLong(portletRequest, "plid");
1461    
1462                    Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
1463    
1464                    Group stagingGroup = null;
1465                    Group liveGroup = null;
1466    
1467                    Layout targetLayout = null;
1468    
1469                    long scopeGroupId = PortalUtil.getScopeGroupId(portletRequest);
1470    
1471                    if (sourceLayout.isTypeControlPanel()) {
1472                            stagingGroup = GroupLocalServiceUtil.fetchGroup(scopeGroupId);
1473                            liveGroup = stagingGroup.getLiveGroup();
1474    
1475                            targetLayout = sourceLayout;
1476                    }
1477                    else if (sourceLayout.hasScopeGroup() &&
1478                                     (sourceLayout.getScopeGroup().getGroupId() == scopeGroupId)) {
1479    
1480                            stagingGroup = sourceLayout.getScopeGroup();
1481                            liveGroup = stagingGroup.getLiveGroup();
1482    
1483                            targetLayout = LayoutLocalServiceUtil.getLayout(
1484                                    liveGroup.getClassPK());
1485                    }
1486                    else {
1487                            stagingGroup = sourceLayout.getGroup();
1488                            liveGroup = stagingGroup.getLiveGroup();
1489    
1490                            targetLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
1491                                    sourceLayout.getUuid(), liveGroup.getGroupId(),
1492                                    sourceLayout.isPrivateLayout());
1493                    }
1494    
1495                    copyPortlet(
1496                            portletRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
1497                            sourceLayout.getPlid(), targetLayout.getPlid(),
1498                            portlet.getPortletId());
1499            }
1500    
1501            @Override
1502            public void publishToRemote(PortletRequest portletRequest)
1503                    throws PortalException {
1504    
1505                    publishToRemote(portletRequest, false);
1506            }
1507    
1508            @Override
1509            public void scheduleCopyFromLive(PortletRequest portletRequest)
1510                    throws PortalException {
1511    
1512                    long stagingGroupId = ParamUtil.getLong(
1513                            portletRequest, "stagingGroupId");
1514    
1515                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1516    
1517                    long liveGroupId = stagingGroup.getLiveGroupId();
1518    
1519                    Map<String, String[]> parameterMap =
1520                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
1521                                    portletRequest);
1522    
1523                    publishLayouts(
1524                            portletRequest, liveGroupId, stagingGroupId, parameterMap, true);
1525            }
1526    
1527            @Override
1528            public void schedulePublishToLive(PortletRequest portletRequest)
1529                    throws PortalException {
1530    
1531                    long stagingGroupId = ParamUtil.getLong(
1532                            portletRequest, "stagingGroupId");
1533    
1534                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1535    
1536                    long liveGroupId = stagingGroup.getLiveGroupId();
1537    
1538                    Map<String, String[]> parameterMap =
1539                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
1540                                    portletRequest);
1541    
1542                    publishLayouts(
1543                            portletRequest, stagingGroupId, liveGroupId, parameterMap, true);
1544            }
1545    
1546            @Override
1547            public void schedulePublishToRemote(PortletRequest portletRequest)
1548                    throws PortalException {
1549    
1550                    publishToRemote(portletRequest, true);
1551            }
1552    
1553            @Override
1554            public void setRecentLayoutBranchId(
1555                    HttpServletRequest request, long layoutSetBranchId, long plid,
1556                    long layoutBranchId) {
1557    
1558                    PortalPreferences portalPreferences =
1559                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1560    
1561                    setRecentLayoutBranchId(
1562                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1563            }
1564    
1565            @Override
1566            public void setRecentLayoutBranchId(
1567                    User user, long layoutSetBranchId, long plid, long layoutBranchId) {
1568    
1569                    PortalPreferences portalPreferences = getPortalPreferences(user);
1570    
1571                    setRecentLayoutBranchId(
1572                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1573            }
1574    
1575            @Override
1576            public void setRecentLayoutRevisionId(
1577                    HttpServletRequest request, long layoutSetBranchId, long plid,
1578                    long layoutRevisionId) {
1579    
1580                    PortalPreferences portalPreferences =
1581                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1582    
1583                    setRecentLayoutRevisionId(
1584                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1585            }
1586    
1587            @Override
1588            public void setRecentLayoutRevisionId(
1589                    User user, long layoutSetBranchId, long plid, long layoutRevisionId) {
1590    
1591                    PortalPreferences portalPreferences = getPortalPreferences(user);
1592    
1593                    setRecentLayoutRevisionId(
1594                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1595            }
1596    
1597            @Override
1598            public void setRecentLayoutSetBranchId(
1599                    HttpServletRequest request, long layoutSetId, long layoutSetBranchId) {
1600    
1601                    SessionClicks.put(
1602                            request, Staging.class.getName(),
1603                            getRecentLayoutSetBranchIdKey(layoutSetId),
1604                            String.valueOf(layoutSetBranchId));
1605            }
1606    
1607            @Override
1608            public void setRecentLayoutSetBranchId(
1609                    User user, long layoutSetId, long layoutSetBranchId) {
1610    
1611                    PortalPreferences portalPreferences = getPortalPreferences(user);
1612    
1613                    try {
1614                            setRecentLayoutAttribute(
1615                                    portalPreferences, getRecentLayoutSetBranchIdKey(layoutSetId),
1616                                    layoutSetBranchId);
1617                    }
1618                    catch (JSONException jsone) {
1619                            if (_log.isWarnEnabled()) {
1620                                    _log.warn(
1621                                            "Unable to set recent layout set branch ID with user " +
1622                                                    user.getUserId() + " and layout set " + layoutSetId +
1623                                                            " and layout set branch " + layoutSetBranchId,
1624                                            jsone);
1625                            }
1626                    }
1627            }
1628    
1629            @Override
1630            public String stripProtocolFromRemoteAddress(String remoteAddress) {
1631                    if (remoteAddress.startsWith(Http.HTTP_WITH_SLASH)) {
1632                            remoteAddress = remoteAddress.substring(
1633                                    Http.HTTP_WITH_SLASH.length());
1634                    }
1635                    else if (remoteAddress.startsWith(Http.HTTPS_WITH_SLASH)) {
1636                            remoteAddress = remoteAddress.substring(
1637                                    Http.HTTPS_WITH_SLASH.length());
1638                    }
1639    
1640                    return remoteAddress;
1641            }
1642    
1643            /**
1644             * @deprecated As of 7.0.0, see {@link
1645             *             com.liferay.portal.kernel.backgroundtask.BackgroundTaskExecutor#getIsolationLevel(
1646             *             )}
1647             */
1648            @Deprecated
1649            @Override
1650            public void unlockGroup(long groupId) {
1651                    LockManagerUtil.unlock(Staging.class.getName(), groupId);
1652            }
1653    
1654            @Override
1655            public void unscheduleCopyFromLive(PortletRequest portletRequest)
1656                    throws PortalException {
1657    
1658                    long stagingGroupId = ParamUtil.getLong(
1659                            portletRequest, "stagingGroupId");
1660    
1661                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1662                    String groupName = getSchedulerGroupName(
1663                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
1664    
1665                    LayoutServiceUtil.unschedulePublishToLive(
1666                            stagingGroupId, jobName, groupName);
1667            }
1668    
1669            @Override
1670            public void unschedulePublishToLive(PortletRequest portletRequest)
1671                    throws PortalException {
1672    
1673                    long stagingGroupId = ParamUtil.getLong(
1674                            portletRequest, "stagingGroupId");
1675    
1676                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1677    
1678                    long liveGroupId = stagingGroup.getLiveGroupId();
1679    
1680                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1681                    String groupName = getSchedulerGroupName(
1682                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
1683    
1684                    LayoutServiceUtil.unschedulePublishToLive(
1685                            liveGroupId, jobName, groupName);
1686            }
1687    
1688            @Override
1689            public void unschedulePublishToRemote(PortletRequest portletRequest)
1690                    throws PortalException {
1691    
1692                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1693    
1694                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1695                    String groupName = getSchedulerGroupName(
1696                            DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1697    
1698                    LayoutServiceUtil.unschedulePublishToRemote(
1699                            groupId, jobName, groupName);
1700            }
1701    
1702            @Override
1703            public void updateLastImportSettings(
1704                    Element layoutElement, Layout layout,
1705                    PortletDataContext portletDataContext) {
1706    
1707                    Map<String, String[]> parameterMap =
1708                            portletDataContext.getParameterMap();
1709    
1710                    String cmd = MapUtil.getString(parameterMap, Constants.CMD);
1711    
1712                    if (!cmd.equals(Constants.PUBLISH_TO_LIVE)) {
1713                            return;
1714                    }
1715    
1716                    UnicodeProperties typeSettingsProperties =
1717                            layout.getTypeSettingsProperties();
1718    
1719                    typeSettingsProperties.setProperty(
1720                            "last-import-date", String.valueOf(System.currentTimeMillis()));
1721    
1722                    String layoutRevisionId = GetterUtil.getString(
1723                            layoutElement.attributeValue("layout-revision-id"));
1724    
1725                    typeSettingsProperties.setProperty(
1726                            "last-import-layout-revision-id", layoutRevisionId);
1727    
1728                    String layoutSetBranchId = MapUtil.getString(
1729                            parameterMap, "layoutSetBranchId");
1730    
1731                    typeSettingsProperties.setProperty(
1732                            "last-import-layout-set-branch-id", layoutSetBranchId);
1733    
1734                    String layoutSetBranchName = MapUtil.getString(
1735                            parameterMap, "layoutSetBranchName");
1736    
1737                    typeSettingsProperties.setProperty(
1738                            "last-import-layout-set-branch-name", layoutSetBranchName);
1739    
1740                    String lastImportUserName = MapUtil.getString(
1741                            parameterMap, "lastImportUserName");
1742    
1743                    typeSettingsProperties.setProperty(
1744                            "last-import-user-name", lastImportUserName);
1745    
1746                    String lastImportUserUuid = MapUtil.getString(
1747                            parameterMap, "lastImportUserUuid");
1748    
1749                    typeSettingsProperties.setProperty(
1750                            "last-import-user-uuid", lastImportUserUuid);
1751    
1752                    String layoutBranchId = GetterUtil.getString(
1753                            layoutElement.attributeValue("layout-branch-id"));
1754    
1755                    typeSettingsProperties.setProperty(
1756                            "last-import-layout-branch-id", layoutBranchId);
1757    
1758                    String layoutBranchName = GetterUtil.getString(
1759                            layoutElement.attributeValue("layout-branch-name"));
1760    
1761                    typeSettingsProperties.setProperty(
1762                            "last-import-layout-branch-name", layoutBranchName);
1763    
1764                    layout.setTypeSettingsProperties(typeSettingsProperties);
1765            }
1766    
1767            /**
1768             * @deprecated As of 7.0.0, replaced by {@link
1769             *             ExportImportDateUtil#updateLastPublishDate(long, boolean,
1770             *             DateRange, Date)}
1771             */
1772            @Deprecated
1773            @Override
1774            public void updateLastPublishDate(
1775                            long groupId, boolean privateLayout, Date lastPublishDate)
1776                    throws PortalException {
1777    
1778                    ExportImportDateUtil.updateLastPublishDate(
1779                            groupId, privateLayout, null, lastPublishDate);
1780            }
1781    
1782            /**
1783             * @deprecated As of 7.0.0, replaced by {@link
1784             *             ExportImportDateUtil#updateLastPublishDate(String,
1785             *             PortletPreferences, DateRange, Date)}
1786             */
1787            @Deprecated
1788            @Override
1789            public void updateLastPublishDate(
1790                    String portletId, PortletPreferences portletPreferences,
1791                    Date lastPublishDate) {
1792    
1793                    ExportImportDateUtil.updateLastPublishDate(
1794                            portletId, portletPreferences, null, lastPublishDate);
1795            }
1796    
1797            @Override
1798            public void updateStaging(PortletRequest portletRequest, Group liveGroup)
1799                    throws PortalException {
1800    
1801                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1802                            WebKeys.THEME_DISPLAY);
1803    
1804                    PermissionChecker permissionChecker =
1805                            themeDisplay.getPermissionChecker();
1806    
1807                    long userId = permissionChecker.getUserId();
1808    
1809                    if (!GroupPermissionUtil.contains(
1810                                    permissionChecker, liveGroup, ActionKeys.MANAGE_STAGING)) {
1811    
1812                            return;
1813                    }
1814    
1815                    int stagingType = getStagingType(portletRequest, liveGroup);
1816    
1817                    boolean branchingPublic = getBoolean(
1818                            portletRequest, liveGroup, "branchingPublic");
1819                    boolean branchingPrivate = getBoolean(
1820                            portletRequest, liveGroup, "branchingPrivate");
1821                    boolean forceDisable = ParamUtil.getBoolean(
1822                            portletRequest, "forceDisable");
1823    
1824                    ServiceContext serviceContext =
1825                            ServiceContextThreadLocal.getServiceContext();
1826    
1827                    serviceContext.setAttribute("forceDisable", forceDisable);
1828    
1829                    if (stagingType == StagingConstants.TYPE_NOT_STAGED) {
1830                            if (liveGroup.hasStagingGroup() || liveGroup.isStagedRemotely()) {
1831                                    StagingLocalServiceUtil.disableStaging(
1832                                            portletRequest, liveGroup, serviceContext);
1833                            }
1834                    }
1835                    else if (stagingType == StagingConstants.TYPE_LOCAL_STAGING) {
1836                            StagingLocalServiceUtil.enableLocalStaging(
1837                                    userId, liveGroup, branchingPublic, branchingPrivate,
1838                                    serviceContext);
1839                    }
1840                    else if (stagingType == StagingConstants.TYPE_REMOTE_STAGING) {
1841                            String remoteAddress = getString(
1842                                    portletRequest, liveGroup, "remoteAddress");
1843    
1844                            remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
1845    
1846                            int remotePort = getInteger(
1847                                    portletRequest, liveGroup, "remotePort");
1848                            String remotePathContext = getString(
1849                                    portletRequest, liveGroup, "remotePathContext");
1850                            boolean secureConnection = getBoolean(
1851                                    portletRequest, liveGroup, "secureConnection");
1852                            long remoteGroupId = getLong(
1853                                    portletRequest, liveGroup, "remoteGroupId");
1854    
1855                            StagingLocalServiceUtil.enableRemoteStaging(
1856                                    userId, liveGroup, branchingPublic, branchingPrivate,
1857                                    remoteAddress, remotePort, remotePathContext, secureConnection,
1858                                    remoteGroupId, serviceContext);
1859                    }
1860            }
1861    
1862            @Override
1863            public void validateRemote(
1864                            long groupId, String remoteAddress, int remotePort,
1865                            String remotePathContext, boolean secureConnection,
1866                            long remoteGroupId)
1867                    throws PortalException {
1868    
1869                    RemoteOptionsException roe = null;
1870    
1871                    if (!Validator.isDomain(remoteAddress) &&
1872                            !Validator.isIPAddress(remoteAddress)) {
1873    
1874                            roe = new RemoteOptionsException(
1875                                    RemoteOptionsException.REMOTE_ADDRESS);
1876    
1877                            roe.setRemoteAddress(remoteAddress);
1878    
1879                            throw roe;
1880                    }
1881    
1882                    if ((remotePort < 1) || (remotePort > 65535)) {
1883                            roe = new RemoteOptionsException(
1884                                    RemoteOptionsException.REMOTE_PORT);
1885    
1886                            roe.setRemotePort(remotePort);
1887    
1888                            throw roe;
1889                    }
1890    
1891                    if (Validator.isNotNull(remotePathContext) &&
1892                            (!remotePathContext.startsWith(StringPool.FORWARD_SLASH) ||
1893                             remotePathContext.endsWith(StringPool.FORWARD_SLASH))) {
1894    
1895                            roe = new RemoteOptionsException(
1896                                    RemoteOptionsException.REMOTE_PATH_CONTEXT);
1897    
1898                            roe.setRemotePathContext(remotePathContext);
1899    
1900                            throw roe;
1901                    }
1902    
1903                    validateRemoteGroup(
1904                            groupId, remoteGroupId, remoteAddress, remotePort,
1905                            remotePathContext, secureConnection);
1906            }
1907    
1908            /**
1909             * @deprecated As of 7.0.0, replaced by {@link #validateRemote(long, String,
1910             *             int, String, boolean, long)}
1911             */
1912            @Deprecated
1913            @Override
1914            public void validateRemote(
1915                    String remoteAddress, int remotePort, String remotePathContext,
1916                    boolean secureConnection, long remoteGroupId) {
1917            }
1918    
1919            protected void deleteRecentLayoutRevisionId(
1920                    PortalPreferences portalPreferences, long layoutSetBranchId,
1921                    long plid) {
1922    
1923                    String oldPortalPreferences = portalPreferences.getValue(
1924                            Staging.class.getName(),
1925                            StagingConstants.STAGING_RECENT_LAYOUT_IDS_MAP);
1926    
1927                    try {
1928                            JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
1929    
1930                            JSONArray oldJsonArray = JSONFactoryUtil.createJSONArray(
1931                                    oldPortalPreferences);
1932    
1933                            String recentLayoutRevisionIdKey = getRecentLayoutRevisionIdKey(
1934                                    layoutSetBranchId, plid);
1935    
1936                            for (int i = 0; i < oldJsonArray.length(); i ++) {
1937                                    JSONObject jsonObject = oldJsonArray.getJSONObject(i);
1938    
1939                                    if (Validator.isNotNull(
1940                                                    jsonObject.getString(recentLayoutRevisionIdKey))) {
1941    
1942                                            continue;
1943                                    }
1944    
1945                                    jsonArray.put(jsonObject);
1946                            }
1947    
1948                            portalPreferences.setValue(
1949                                    Staging.class.getName(),
1950                                    StagingConstants.STAGING_RECENT_LAYOUT_IDS_MAP,
1951                                    jsonArray.toString());
1952                    }
1953                    catch (JSONException jsone) {
1954                            if (_log.isWarnEnabled()) {
1955                                    _log.warn(
1956                                            "Unable to delete recent layout revision ID with layout " +
1957                                                    "set branch " + layoutSetBranchId + " and PLID " + plid,
1958                                            jsone);
1959                            }
1960                    }
1961            }
1962    
1963            protected void doCopyRemoteLayouts(
1964                            ExportImportConfiguration exportImportConfiguration,
1965                            String remoteAddress, int remotePort, String remotePathContext,
1966                            boolean secureConnection, boolean remotePrivateLayout)
1967                    throws PortalException {
1968    
1969                    Map<String, Serializable> taskContextMap = new HashMap<>();
1970    
1971                    taskContextMap.put(Constants.CMD, Constants.PUBLISH_TO_REMOTE);
1972                    taskContextMap.put(
1973                            "exportImportConfigurationId",
1974                            exportImportConfiguration.getExportImportConfigurationId());
1975    
1976                    String remoteURL = buildRemoteURL(
1977                            remoteAddress, remotePort, remotePathContext, secureConnection,
1978                            GroupConstants.DEFAULT_LIVE_GROUP_ID, remotePrivateLayout);
1979    
1980                    PermissionChecker permissionChecker =
1981                            PermissionThreadLocal.getPermissionChecker();
1982    
1983                    User user = permissionChecker.getUser();
1984    
1985                    HttpPrincipal httpPrincipal = new HttpPrincipal(
1986                            remoteURL, user.getLogin(), user.getPassword(),
1987                            user.getPasswordEncrypted());
1988    
1989                    taskContextMap.put("httpPrincipal", httpPrincipal);
1990    
1991                    BackgroundTaskLocalServiceUtil.addBackgroundTask(
1992                            user.getUserId(), exportImportConfiguration.getGroupId(),
1993                            StringPool.BLANK, null,
1994                            LayoutRemoteStagingBackgroundTaskExecutor.class, taskContextMap,
1995                            new ServiceContext());
1996            }
1997    
1998            protected boolean getBoolean(
1999                    PortletRequest portletRequest, Group group, String param) {
2000    
2001                    return ParamUtil.getBoolean(
2002                            portletRequest, param,
2003                            GetterUtil.getBoolean(group.getTypeSettingsProperty(param)));
2004            }
2005    
2006            protected int getInteger(
2007                    PortletRequest portletRequest, Group group, String param) {
2008    
2009                    return ParamUtil.getInteger(
2010                            portletRequest, param,
2011                            GetterUtil.getInteger(group.getTypeSettingsProperty(param)));
2012            }
2013    
2014            protected long getLong(
2015                    PortletRequest portletRequest, Group group, String param) {
2016    
2017                    return ParamUtil.getLong(
2018                            portletRequest, param,
2019                            GetterUtil.getLong(group.getTypeSettingsProperty(param)));
2020            }
2021    
2022            protected PortalPreferences getPortalPreferences(User user) {
2023                    boolean signedIn = !user.isDefaultUser();
2024    
2025                    return PortletPreferencesFactoryUtil.getPortalPreferences(
2026                            user.getUserId(), signedIn);
2027            }
2028    
2029            protected long getRecentLayoutBranchId(
2030                    PortalPreferences portalPreferences, long layoutSetBranchId,
2031                    long plid) {
2032    
2033                    try {
2034                            return getRecentLayoutAttribute(
2035                                    portalPreferences,
2036                                    getRecentLayoutBranchIdKey(layoutSetBranchId, plid));
2037                    }
2038                    catch (JSONException jsone) {
2039                            if (_log.isWarnEnabled()) {
2040                                    _log.warn(
2041                                            "Unable to get recent layout branch ID with layout set " +
2042                                                    "branch " + layoutSetBranchId + " and PLID " + plid,
2043                                            jsone);
2044                            }
2045                    }
2046    
2047                    return 0;
2048            }
2049    
2050            protected String getRecentLayoutBranchIdKey(
2051                    long layoutSetBranchId, long plid) {
2052    
2053                    StringBundler sb = new StringBundler(4);
2054    
2055                    sb.append("layoutBranchId-");
2056                    sb.append(layoutSetBranchId);
2057                    sb.append(StringPool.DASH);
2058                    sb.append(plid);
2059    
2060                    return sb.toString();
2061            }
2062    
2063            protected long getRecentLayoutRevisionId(
2064                            PortalPreferences portalPreferences, long layoutSetBranchId,
2065                            long plid)
2066                    throws PortalException {
2067    
2068                    long layoutRevisionId = 0;
2069    
2070                    try {
2071                            layoutRevisionId = getRecentLayoutAttribute(
2072                                    portalPreferences,
2073                                    getRecentLayoutRevisionIdKey(layoutSetBranchId, plid));
2074                    }
2075                    catch (JSONException jsone) {
2076                            if (_log.isWarnEnabled()) {
2077                                    _log.warn(
2078                                            "Unable to get recent layout revision ID with layout set " +
2079                                                    "branch " + layoutSetBranchId + " and PLID " + plid,
2080                                            jsone);
2081                            }
2082                    }
2083    
2084                    if (layoutRevisionId > 0) {
2085                            return layoutRevisionId;
2086                    }
2087    
2088                    long layoutBranchId = getRecentLayoutBranchId(
2089                            portalPreferences, layoutSetBranchId, plid);
2090    
2091                    if (layoutBranchId > 0) {
2092                            try {
2093                                    LayoutBranchLocalServiceUtil.getLayoutBranch(layoutBranchId);
2094                            }
2095                            catch (NoSuchLayoutBranchException nslbe) {
2096                                    LayoutBranch layoutBranch =
2097                                            LayoutBranchLocalServiceUtil.getMasterLayoutBranch(
2098                                                    layoutSetBranchId, plid);
2099    
2100                                    layoutBranchId = layoutBranch.getLayoutBranchId();
2101                            }
2102                    }
2103    
2104                    if (layoutBranchId > 0) {
2105                            try {
2106                                    LayoutRevision layoutRevision =
2107                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
2108                                                    layoutSetBranchId, layoutBranchId, plid);
2109    
2110                                    if (layoutRevision != null) {
2111                                            layoutRevisionId = layoutRevision.getLayoutRevisionId();
2112                                    }
2113                            }
2114                            catch (NoSuchLayoutRevisionException nslre) {
2115                            }
2116                    }
2117    
2118                    return layoutRevisionId;
2119            }
2120    
2121            protected String getRecentLayoutRevisionIdKey(
2122                    long layoutSetBranchId, long plid) {
2123    
2124                    StringBundler sb = new StringBundler(4);
2125    
2126                    sb.append("layoutRevisionId-");
2127                    sb.append(layoutSetBranchId);
2128                    sb.append(StringPool.DASH);
2129                    sb.append(plid);
2130    
2131                    return sb.toString();
2132            }
2133    
2134            protected String getRecentLayoutSetBranchIdKey(long layoutSetId) {
2135                    return "layoutSetBranchId_" + layoutSetId;
2136            }
2137    
2138            protected int getStagingType(
2139                    PortletRequest portletRequest, Group liveGroup) {
2140    
2141                    String stagingType = portletRequest.getParameter("stagingType");
2142    
2143                    if (stagingType != null) {
2144                            return GetterUtil.getInteger(stagingType);
2145                    }
2146    
2147                    if (liveGroup.isStagedRemotely()) {
2148                            return StagingConstants.TYPE_REMOTE_STAGING;
2149                    }
2150    
2151                    if (liveGroup.hasStagingGroup()) {
2152                            return StagingConstants.TYPE_LOCAL_STAGING;
2153                    }
2154    
2155                    return StagingConstants.TYPE_NOT_STAGED;
2156            }
2157    
2158            protected String getString(
2159                    PortletRequest portletRequest, Group group, String param) {
2160    
2161                    return ParamUtil.getString(
2162                            portletRequest, param,
2163                            GetterUtil.getString(group.getTypeSettingsProperty(param)));
2164            }
2165    
2166            protected boolean isCompanyGroup(HttpPrincipal httpPrincipal, Group group) {
2167                    ClassName className = ClassNameServiceHttp.fetchClassName(
2168                            httpPrincipal, String.valueOf(group.getClassNameId()));
2169    
2170                    if (Validator.equals(
2171                                    className.getClassName(), Company.class.getName())) {
2172    
2173                            return true;
2174                    }
2175    
2176                    return false;
2177            }
2178    
2179            protected void publishLayouts(
2180                            PortletRequest portletRequest, long sourceGroupId,
2181                            long targetGroupId, Map<String, String[]> parameterMap,
2182                            boolean schedule)
2183                    throws PortalException {
2184    
2185                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
2186                            WebKeys.THEME_DISPLAY);
2187    
2188                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
2189    
2190                    boolean privateLayout = true;
2191    
2192                    if (tabs1.equals("public-pages")) {
2193                            privateLayout = false;
2194                    }
2195    
2196                    String scope = ParamUtil.getString(portletRequest, "scope");
2197    
2198                    long[] layoutIds = null;
2199    
2200                    if (scope.equals("selected-pages")) {
2201                            layoutIds = ExportImportHelperUtil.getLayoutIds(
2202                                    portletRequest, targetGroupId);
2203                    }
2204    
2205                    if (schedule) {
2206                            String groupName = getSchedulerGroupName(
2207                                    DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
2208    
2209                            int recurrenceType = ParamUtil.getInteger(
2210                                    portletRequest, "recurrenceType");
2211    
2212                            Calendar startCalendar = ExportImportDateUtil.getCalendar(
2213                                    portletRequest, "schedulerStartDate", true);
2214    
2215                            String cronText = SchedulerEngineHelperUtil.getCronText(
2216                                    portletRequest, startCalendar, true, recurrenceType);
2217    
2218                            Date schedulerEndDate = null;
2219    
2220                            int endDateType = ParamUtil.getInteger(
2221                                    portletRequest, "endDateType");
2222    
2223                            if (endDateType == 1) {
2224                                    Calendar endCalendar = ExportImportDateUtil.getCalendar(
2225                                            portletRequest, "schedulerEndDate", true);
2226    
2227                                    schedulerEndDate = endCalendar.getTime();
2228                            }
2229    
2230                            String description = ParamUtil.getString(
2231                                    portletRequest, "description");
2232    
2233                            LayoutServiceUtil.schedulePublishToLive(
2234                                    sourceGroupId, targetGroupId, privateLayout, layoutIds,
2235                                    parameterMap, scope, null, null, groupName, cronText,
2236                                    startCalendar.getTime(), schedulerEndDate, description);
2237                    }
2238                    else {
2239                            if (scope.equals("all-pages")) {
2240                                    publishLayouts(
2241                                            themeDisplay.getUserId(), sourceGroupId, targetGroupId,
2242                                            privateLayout, parameterMap);
2243                            }
2244                            else {
2245                                    publishLayouts(
2246                                            themeDisplay.getUserId(), sourceGroupId, targetGroupId,
2247                                            privateLayout, layoutIds, parameterMap);
2248                            }
2249                    }
2250            }
2251    
2252            protected void publishToRemote(
2253                            PortletRequest portletRequest, boolean schedule)
2254                    throws PortalException {
2255    
2256                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
2257    
2258                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
2259    
2260                    boolean privateLayout = true;
2261    
2262                    if (tabs1.equals("public-pages")) {
2263                            privateLayout = false;
2264                    }
2265    
2266                    String scope = ParamUtil.getString(portletRequest, "scope");
2267    
2268                    if (Validator.isNull(scope)) {
2269                            scope = "all-pages";
2270                    }
2271    
2272                    Map<Long, Boolean> layoutIdMap = null;
2273    
2274                    if (scope.equals("selected-pages")) {
2275                            layoutIdMap = ExportImportHelperUtil.getLayoutIdMap(portletRequest);
2276                    }
2277    
2278                    Map<String, String[]> parameterMap =
2279                            ExportImportConfigurationParameterMapFactory.buildParameterMap(
2280                                    portletRequest);
2281    
2282                    Group group = GroupLocalServiceUtil.getGroup(groupId);
2283    
2284                    UnicodeProperties groupTypeSettingsProperties =
2285                            group.getTypeSettingsProperties();
2286    
2287                    String remoteAddress = ParamUtil.getString(
2288                            portletRequest, "remoteAddress",
2289                            groupTypeSettingsProperties.getProperty("remoteAddress"));
2290    
2291                    remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
2292    
2293                    int remotePort = ParamUtil.getInteger(
2294                            portletRequest, "remotePort",
2295                            GetterUtil.getInteger(
2296                                    groupTypeSettingsProperties.getProperty("remotePort")));
2297                    String remotePathContext = ParamUtil.getString(
2298                            portletRequest, "remotePathContext",
2299                            groupTypeSettingsProperties.getProperty("remotePathContext"));
2300                    boolean secureConnection = ParamUtil.getBoolean(
2301                            portletRequest, "secureConnection",
2302                            GetterUtil.getBoolean(
2303                                    groupTypeSettingsProperties.getProperty("secureConnection")));
2304                    long remoteGroupId = ParamUtil.getLong(
2305                            portletRequest, "remoteGroupId",
2306                            GetterUtil.getLong(
2307                                    groupTypeSettingsProperties.getProperty("remoteGroupId")));
2308                    boolean remotePrivateLayout = ParamUtil.getBoolean(
2309                            portletRequest, "remotePrivateLayout");
2310    
2311                    validateRemote(
2312                            groupId, remoteAddress, remotePort, remotePathContext,
2313                            secureConnection, remoteGroupId);
2314    
2315                    if (schedule) {
2316                            String groupName = getSchedulerGroupName(
2317                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
2318    
2319                            int recurrenceType = ParamUtil.getInteger(
2320                                    portletRequest, "recurrenceType");
2321    
2322                            Calendar startCalendar = ExportImportDateUtil.getCalendar(
2323                                    portletRequest, "schedulerStartDate", true);
2324    
2325                            String cronText = SchedulerEngineHelperUtil.getCronText(
2326                                    portletRequest, startCalendar, true, recurrenceType);
2327    
2328                            Date schedulerEndDate = null;
2329    
2330                            int endDateType = ParamUtil.getInteger(
2331                                    portletRequest, "endDateType");
2332    
2333                            if (endDateType == 1) {
2334                                    Calendar endCalendar = ExportImportDateUtil.getCalendar(
2335                                            portletRequest, "schedulerEndDate", true);
2336    
2337                                    schedulerEndDate = endCalendar.getTime();
2338                            }
2339    
2340                            String description = ParamUtil.getString(
2341                                    portletRequest, "description");
2342    
2343                            LayoutServiceUtil.schedulePublishToRemote(
2344                                    groupId, privateLayout, layoutIdMap, parameterMap,
2345                                    remoteAddress, remotePort, remotePathContext, secureConnection,
2346                                    remoteGroupId, remotePrivateLayout, null, null, groupName,
2347                                    cronText, startCalendar.getTime(), schedulerEndDate,
2348                                    description);
2349                    }
2350                    else {
2351                            copyRemoteLayouts(
2352                                    groupId, privateLayout, layoutIdMap, parameterMap,
2353                                    remoteAddress, remotePort, remotePathContext, secureConnection,
2354                                    remoteGroupId, remotePrivateLayout);
2355                    }
2356            }
2357    
2358            protected void setRecentLayoutBranchId(
2359                    PortalPreferences portalPreferences, long layoutSetBranchId, long plid,
2360                    long layoutBranchId) {
2361    
2362                    try {
2363                            setRecentLayoutAttribute(
2364                                    portalPreferences,
2365                                    getRecentLayoutBranchIdKey(layoutSetBranchId, plid),
2366                                    layoutBranchId);
2367                    }
2368                    catch (JSONException jsone) {
2369                            if (_log.isWarnEnabled()) {
2370                                    _log.warn(
2371                                            "Unable to set recent layout branch ID with layout set " +
2372                                                    "branch " + layoutSetBranchId + " and PLID " + plid +
2373                                                            " and layout branch " + layoutBranchId,
2374                                            jsone);
2375                            }
2376                    }
2377            }
2378    
2379            protected void setRecentLayoutRevisionId(
2380                    PortalPreferences portalPreferences, long layoutSetBranchId, long plid,
2381                    long layoutRevisionId) {
2382    
2383                    long layoutBranchId = 0;
2384    
2385                    try {
2386                            LayoutRevision layoutRevision =
2387                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2388                                            layoutRevisionId);
2389    
2390                            layoutBranchId = layoutRevision.getLayoutBranchId();
2391    
2392                            LayoutRevision lastLayoutRevision =
2393                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2394                                            layoutSetBranchId, layoutBranchId, plid);
2395    
2396                            if (lastLayoutRevision.getLayoutRevisionId() == layoutRevisionId) {
2397                                    deleteRecentLayoutRevisionId(
2398                                            portalPreferences, layoutSetBranchId, plid);
2399                            }
2400                            else {
2401                                    setRecentLayoutAttribute(
2402                                            portalPreferences,
2403                                            getRecentLayoutRevisionIdKey(layoutSetBranchId, plid),
2404                                            layoutRevisionId);
2405                            }
2406                    }
2407                    catch (PortalException pe) {
2408                            if (_log.isWarnEnabled()) {
2409                                    _log.warn(
2410                                            "Unable to set recent layout revision ID with layout set " +
2411                                                    "branch " + layoutSetBranchId + " and PLID " + plid +
2412                                                            " and layout branch " + layoutBranchId,
2413                                            pe);
2414                            }
2415                    }
2416    
2417                    setRecentLayoutBranchId(
2418                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
2419            }
2420    
2421            protected void validateRemoteGroup(
2422                            long groupId, long remoteGroupId, String remoteAddress,
2423                            int remotePort, String remotePathContext, boolean secureConnection)
2424                    throws PortalException {
2425    
2426                    if (remoteGroupId <= 0) {
2427                            RemoteOptionsException roe = new RemoteOptionsException(
2428                                    RemoteOptionsException.REMOTE_GROUP_ID);
2429    
2430                            roe.setRemoteGroupId(remoteGroupId);
2431    
2432                            throw roe;
2433                    }
2434    
2435                    PermissionChecker permissionChecker =
2436                            PermissionThreadLocal.getPermissionChecker();
2437    
2438                    User user = permissionChecker.getUser();
2439    
2440                    String remoteURL = buildRemoteURL(
2441                            remoteAddress, remotePort, remotePathContext, secureConnection,
2442                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
2443    
2444                    HttpPrincipal httpPrincipal = new HttpPrincipal(
2445                            remoteURL, user.getLogin(), user.getPassword(),
2446                            user.getPasswordEncrypted());
2447    
2448                    try {
2449    
2450                            // Ping the remote host and verify that the remote group exists in
2451                            // the same company as the remote user
2452    
2453                            GroupServiceHttp.checkRemoteStagingGroup(
2454                                    httpPrincipal, remoteGroupId);
2455    
2456                            // Ensure that the local group and the remote group are not the same
2457                            // group and that they are either both company groups or both not
2458                            // company groups
2459    
2460                            Group group = GroupLocalServiceUtil.getGroup(groupId);
2461    
2462                            Group remoteGroup = GroupServiceHttp.getGroup(
2463                                    httpPrincipal, remoteGroupId);
2464    
2465                            if (group.isCompany() ^
2466                                    isCompanyGroup(httpPrincipal, remoteGroup)) {
2467    
2468                                    RemoteExportException ree = new RemoteExportException(
2469                                            RemoteExportException.INVALID_GROUP);
2470    
2471                                    ree.setGroupId(remoteGroupId);
2472    
2473                                    throw ree;
2474                            }
2475                    }
2476                    catch (NoSuchGroupException nsge) {
2477                            RemoteExportException ree = new RemoteExportException(
2478                                    RemoteExportException.NO_GROUP);
2479    
2480                            ree.setGroupId(remoteGroupId);
2481    
2482                            throw ree;
2483                    }
2484                    catch (PrincipalException pe) {
2485                            RemoteExportException ree = new RemoteExportException(
2486                                    RemoteExportException.NO_PERMISSIONS);
2487    
2488                            ree.setGroupId(remoteGroupId);
2489    
2490                            throw ree;
2491                    }
2492                    catch (RemoteAuthException rae) {
2493                            rae.setURL(remoteURL);
2494    
2495                            throw rae;
2496                    }
2497                    catch (SystemException se) {
2498                            RemoteExportException ree = new RemoteExportException(
2499                                    RemoteExportException.BAD_CONNECTION, se.getMessage());
2500    
2501                            ree.setURL(remoteURL);
2502    
2503                            throw ree;
2504                    }
2505            }
2506    
2507            private long getRecentLayoutAttribute(
2508                            PortalPreferences portalPreferences, String key)
2509                    throws JSONException {
2510    
2511                    String preferencesString = portalPreferences.getValue(
2512                            Staging.class.getName(),
2513                            StagingConstants.STAGING_RECENT_LAYOUT_IDS_MAP);
2514    
2515                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray(
2516                            preferencesString);
2517    
2518                    for (int i = 0; i < jsonArray.length(); i++) {
2519                            JSONObject jsonObject = jsonArray.getJSONObject(i);
2520    
2521                            if (jsonObject.has(key)) {
2522                                    return GetterUtil.getLong(jsonObject.getString(key));
2523                            }
2524                    }
2525    
2526                    return 0;
2527            }
2528    
2529            private void setRecentLayoutAttribute(
2530                            PortalPreferences portalPreferences, String key, long value)
2531                    throws JSONException {
2532    
2533                    String oldPortalPreferences = portalPreferences.getValue(
2534                            Staging.class.getName(),
2535                            StagingConstants.STAGING_RECENT_LAYOUT_IDS_MAP);
2536    
2537                    JSONArray oldJsonArray = JSONFactoryUtil.createJSONArray(
2538                            oldPortalPreferences);
2539    
2540                    boolean alreadyExists = false;
2541    
2542                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
2543    
2544                    for (int i = 0; i < oldJsonArray.length(); i++) {
2545                            JSONObject jsonObject = oldJsonArray.getJSONObject(i);
2546    
2547                            if (Validator.isNotNull(jsonObject.getString(key))) {
2548                                    alreadyExists = true;
2549    
2550                                    jsonObject.remove(key);
2551    
2552                                    jsonObject.put(key, String.valueOf(value));
2553                            }
2554    
2555                            jsonArray.put(jsonObject);
2556                    }
2557    
2558                    if (!alreadyExists) {
2559                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
2560    
2561                            jsonObject.put(key, String.valueOf(value));
2562    
2563                            jsonArray.put(jsonObject);
2564                    }
2565    
2566                    portalPreferences.setValue(
2567                            Staging.class.getName(),
2568                            StagingConstants.STAGING_RECENT_LAYOUT_IDS_MAP,
2569                            jsonArray.toString());
2570            }
2571    
2572            private static final Log _log = LogFactoryUtil.getLog(StagingImpl.class);
2573    
2574    }