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