001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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) {
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 = null;
593    
594                            try {
595                                    group = GroupLocalServiceUtil.fetchGroup(
596                                            missingReference.getGroupId());
597                            }
598                            catch (SystemException se) {
599                            }
600    
601                            if (group != null) {
602                                    errorMessageJSONObject.put(
603                                            "site",
604                                            LanguageUtil.format(
605                                                    locale, "in-site-x", missingReference.getGroupId(),
606                                                    false));
607                            }
608    
609                            errorMessageJSONObject.put(
610                                    "type",
611                                    ResourceActionsUtil.getModelResource(
612                                            locale, missingReference.getClassName()));
613    
614                            errorMessagesJSONArray.put(errorMessageJSONObject);
615                    }
616    
617                    return errorMessagesJSONArray;
618            }
619    
620            @Override
621            public JSONObject getExceptionMessagesJSONObject(
622                    Locale locale, Exception e, Map<String, Serializable> contextMap) {
623    
624                    JSONObject exceptionMessagesJSONObject =
625                            JSONFactoryUtil.createJSONObject();
626    
627                    String errorMessage = StringPool.BLANK;
628                    JSONArray errorMessagesJSONArray = null;
629                    int errorType = 0;
630                    JSONArray warningMessagesJSONArray = null;
631    
632                    if (e instanceof DuplicateFileException) {
633                            errorMessage = LanguageUtil.get(
634                                    locale, "please-enter-a-unique-document-name");
635                            errorType = ServletResponseConstants.SC_DUPLICATE_FILE_EXCEPTION;
636                    }
637                    else if (e instanceof FileExtensionException) {
638                            errorMessage = LanguageUtil.format(
639                                    locale,
640                                    "document-names-must-end-with-one-of-the-following-extensions",
641                                    ".lar");
642                            errorType = ServletResponseConstants.SC_FILE_EXTENSION_EXCEPTION;
643                    }
644                    else if (e instanceof FileNameException) {
645                            errorMessage = LanguageUtil.get(
646                                    locale, "please-enter-a-file-with-a-valid-file-name");
647                            errorType = ServletResponseConstants.SC_FILE_NAME_EXCEPTION;
648                    }
649                    else if (e instanceof FileSizeException ||
650                                     e instanceof LARFileSizeException) {
651    
652                            long fileMaxSize = PropsValues.DL_FILE_MAX_SIZE;
653    
654                            try {
655                                    fileMaxSize = PrefsPropsUtil.getLong(
656                                            PropsKeys.DL_FILE_MAX_SIZE);
657    
658                                    if (fileMaxSize == 0) {
659                                            fileMaxSize = PrefsPropsUtil.getLong(
660                                                    PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_MAX_SIZE);
661                                    }
662                            }
663                            catch (Exception ex) {
664                            }
665    
666                            errorMessage = LanguageUtil.format(
667                                    locale,
668                                    "please-enter-a-file-with-a-valid-file-size-no-larger-than-x",
669                                    fileMaxSize/1024);
670                            errorType = ServletResponseConstants.SC_FILE_SIZE_EXCEPTION;
671                    }
672                    else if (e instanceof LARTypeException) {
673                            LARTypeException lte = (LARTypeException)e;
674    
675                            errorMessage = LanguageUtil.format(
676                                    locale,
677                                    "please-import-a-lar-file-of-the-correct-type-x-is-not-valid",
678                                    lte.getMessage());
679                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
680                    }
681                    else if (e instanceof LARFileException) {
682                            errorMessage = LanguageUtil.get(
683                                    locale, "please-specify-a-lar-file-to-import");
684                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
685                    }
686                    else if (e instanceof LayoutPrototypeException) {
687                            LayoutPrototypeException lpe = (LayoutPrototypeException)e;
688    
689                            StringBundler sb = new StringBundler(4);
690    
691                            sb.append("the-lar-file-could-not-be-imported-because-it-");
692                            sb.append("requires-page-templates-or-site-templates-that-could-");
693                            sb.append("not-be-found.-please-import-the-following-templates-");
694                            sb.append("manually");
695    
696                            errorMessage = LanguageUtil.get(locale, sb.toString());
697    
698                            errorMessagesJSONArray = JSONFactoryUtil.createJSONArray();
699    
700                            List<Tuple> missingLayoutPrototypes =
701                                    lpe.getMissingLayoutPrototypes();
702    
703                            for (Tuple missingLayoutPrototype : missingLayoutPrototypes) {
704                                    JSONObject errorMessageJSONObject =
705                                            JSONFactoryUtil.createJSONObject();
706    
707                                    String layoutPrototypeUuid =
708                                            (String)missingLayoutPrototype.getObject(1);
709    
710                                    errorMessageJSONObject.put("info", layoutPrototypeUuid);
711    
712                                    String layoutPrototypeName =
713                                            (String)missingLayoutPrototype.getObject(2);
714    
715                                    errorMessageJSONObject.put("name", layoutPrototypeName);
716    
717                                    String layoutPrototypeClassName =
718                                            (String)missingLayoutPrototype.getObject(0);
719    
720                                    errorMessageJSONObject.put(
721                                            "type",
722                                            ResourceActionsUtil.getModelResource(
723                                                    locale, layoutPrototypeClassName));
724    
725                                    errorMessagesJSONArray.put(errorMessageJSONObject);
726                            }
727    
728                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
729                    }
730                    else if (e instanceof LocaleException) {
731                            LocaleException le = (LocaleException)e;
732    
733                            errorMessage = LanguageUtil.format(
734                                    locale,
735                                    "the-available-languages-in-the-lar-file-x-do-not-match-the-" +
736                                            "site's-available-languages-x",
737                                    new String[] {
738                                            StringUtil.merge(
739                                                    le.getSourceAvailableLocales(),
740                                                    StringPool.COMMA_AND_SPACE),
741                                            StringUtil.merge(
742                                                    le.getTargetAvailableLocales(),
743                                                    StringPool.COMMA_AND_SPACE)
744                                    });
745                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
746                    }
747                    else if (e instanceof MissingReferenceException) {
748                            MissingReferenceException mre = (MissingReferenceException)e;
749    
750                            String cmd = null;
751    
752                            if (contextMap != null) {
753                                    cmd = (String)contextMap.get(Constants.CMD);
754                            }
755    
756                            if (Validator.equals(cmd, Constants.PUBLISH_TO_LIVE) ||
757                                    Validator.equals(cmd, Constants.PUBLISH_TO_REMOTE)) {
758    
759                                    errorMessage = LanguageUtil.get(
760                                            locale,
761                                            "there-are-missing-references-that-could-not-be-found-in-" +
762                                                    "the-live-environment");
763                            }
764                            else {
765                                    errorMessage = LanguageUtil.get(
766                                            locale,
767                                            "there-are-missing-references-that-could-not-be-found-in-" +
768                                                    "the-current-site");
769                            }
770    
771                            MissingReferences missingReferences = mre.getMissingReferences();
772    
773                            errorMessagesJSONArray = getErrorMessagesJSONArray(
774                                    locale, missingReferences.getDependencyMissingReferences(),
775                                    contextMap);
776                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
777                            warningMessagesJSONArray = getWarningMessagesJSONArray(
778                                    locale, missingReferences.getWeakMissingReferences(),
779                                    contextMap);
780                    }
781                    else if (e instanceof PortletDataException) {
782                            PortletDataException pde = (PortletDataException)e;
783    
784                            StagedModel stagedModel = pde.getStagedModel();
785    
786                            String referrerClassName = StringPool.BLANK;
787                            String referrerDisplayName = StringPool.BLANK;
788    
789                            if (stagedModel != null) {
790                                    StagedModelType stagedModelType =
791                                            stagedModel.getStagedModelType();
792    
793                                    referrerClassName = stagedModelType.getClassName();
794                                    referrerDisplayName = StagedModelDataHandlerUtil.getDisplayName(
795                                            stagedModel);
796                            }
797    
798                            if (pde.getType() == PortletDataException.INVALID_GROUP) {
799                                    errorMessage = LanguageUtil.format(
800                                            locale,
801                                            "the-x-x-could-not-be-exported-because-it-is-not-in-the-" +
802                                                    "currently-exported-group",
803                                            new String[] {
804                                                    ResourceActionsUtil.getModelResource(
805                                                            locale, referrerClassName),
806                                                    referrerDisplayName
807                                            }
808                                    );
809                            }
810                            else if (pde.getType() == PortletDataException.MISSING_DEPENDENCY) {
811                                    errorMessage = LanguageUtil.format(
812                                            locale,
813                                            "the-x-x-has-missing-references-that-could-not-be-found-" +
814                                                    "during-the-export",
815                                            new String[] {
816                                                    ResourceActionsUtil.getModelResource(
817                                                            locale, referrerClassName),
818                                                    referrerDisplayName
819                                            }
820                                    );
821                            }
822                            else if (pde.getType() == PortletDataException.STATUS_IN_TRASH) {
823                                    errorMessage = LanguageUtil.format(
824                                            locale,
825                                            "the-x-x-could-not-be-exported-because-it-is-in-the-" +
826                                                    "recycle-bin",
827                                            new String[] {
828                                                    ResourceActionsUtil.getModelResource(
829                                                            locale, referrerClassName),
830                                                    referrerDisplayName
831                                            }
832                                    );
833                            }
834                            else if (pde.getType() == PortletDataException.STATUS_UNAVAILABLE) {
835                                    errorMessage = LanguageUtil.format(
836                                            locale,
837                                            "the-x-x-could-not-be-exported-because-its-workflow-" +
838                                                    "status-is-not-exportable",
839                                            new String[] {
840                                                    ResourceActionsUtil.getModelResource(
841                                                            locale, referrerClassName),
842                                                    referrerDisplayName
843                                            }
844                                    );
845                            }
846                            else {
847                                    errorMessage = e.getLocalizedMessage();
848                            }
849    
850                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
851                    }
852                    else if (e instanceof PortletIdException) {
853                            errorMessage = LanguageUtil.get(
854                                    locale, "please-import-a-lar-file-for-the-current-portlet");
855                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
856                    }
857                    else if (e instanceof RemoteExportException) {
858                            RemoteExportException ree = (RemoteExportException)e;
859    
860                            if (ree.getType() == RemoteExportException.NO_LAYOUTS) {
861                                    errorMessage = LanguageUtil.get(
862                                            locale, "no-pages-are-selected-for-export");
863                            }
864    
865                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
866                    }
867                    else {
868                            errorMessage = e.getLocalizedMessage();
869                            errorType = ServletResponseConstants.SC_FILE_CUSTOM_EXCEPTION;
870                    }
871    
872                    exceptionMessagesJSONObject.put("message", errorMessage);
873    
874                    if ((errorMessagesJSONArray != null) &&
875                            (errorMessagesJSONArray.length() > 0)) {
876    
877                            exceptionMessagesJSONObject.put(
878                                    "messageListItems", errorMessagesJSONArray);
879                    }
880    
881                    exceptionMessagesJSONObject.put("status", errorType);
882    
883                    if ((warningMessagesJSONArray != null) &&
884                            (warningMessagesJSONArray.length() > 0)) {
885    
886                            exceptionMessagesJSONObject.put(
887                                    "warningMessages", warningMessagesJSONArray);
888                    }
889    
890                    return exceptionMessagesJSONObject;
891            }
892    
893            @Override
894            public Group getLiveGroup(long groupId)
895                    throws PortalException, SystemException {
896    
897                    if (groupId == 0) {
898                            return null;
899                    }
900    
901                    Group group = GroupLocalServiceUtil.getGroup(groupId);
902    
903                    if (group.isLayout()) {
904                            group = group.getParentGroup();
905                    }
906    
907                    if (group.isStagingGroup()) {
908                            return group.getLiveGroup();
909                    }
910                    else {
911                            return group;
912                    }
913            }
914    
915            @Override
916            public long getLiveGroupId(long groupId)
917                    throws PortalException, SystemException {
918    
919                    if (groupId == 0) {
920                            return groupId;
921                    }
922    
923                    Group group = getLiveGroup(groupId);
924    
925                    return group.getGroupId();
926            }
927    
928            /**
929             * @see LayoutRemoteStagingBackgroundTaskExecutor#getMissingRemoteParentLayouts(
930             *      HttpPrincipal, Layout, long)
931             */
932            @Override
933            public List<Layout> getMissingParentLayouts(Layout layout, long liveGroupId)
934                    throws PortalException, SystemException {
935    
936                    List<Layout> missingParentLayouts = new ArrayList<Layout>();
937    
938                    long parentLayoutId = layout.getParentLayoutId();
939    
940                    Layout parentLayout = null;
941    
942                    while (parentLayoutId > 0) {
943                            parentLayout = LayoutLocalServiceUtil.getLayout(
944                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
945    
946                            try {
947                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
948                                            parentLayout.getUuid(), liveGroupId,
949                                            parentLayout.isPrivateLayout());
950    
951                                    // If one parent is found all others are assumed to exist
952    
953                                    break;
954                            }
955                            catch (NoSuchLayoutException nsle) {
956                                    missingParentLayouts.add(parentLayout);
957    
958                                    parentLayoutId = parentLayout.getParentLayoutId();
959                            }
960                    }
961    
962                    return missingParentLayouts;
963            }
964    
965            @Override
966            public long getRecentLayoutRevisionId(
967                            HttpServletRequest request, long layoutSetBranchId, long plid)
968                    throws PortalException, SystemException {
969    
970                    PortalPreferences portalPreferences =
971                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
972    
973                    return getRecentLayoutRevisionId(
974                            portalPreferences, layoutSetBranchId, plid);
975            }
976    
977            @Override
978            public long getRecentLayoutRevisionId(
979                            User user, long layoutSetBranchId, long plid)
980                    throws PortalException, SystemException {
981    
982                    PortalPreferences portalPreferences = getPortalPreferences(user);
983    
984                    return getRecentLayoutRevisionId(
985                            portalPreferences, layoutSetBranchId, plid);
986            }
987    
988            @Override
989            public long getRecentLayoutSetBranchId(
990                    HttpServletRequest request, long layoutSetId) {
991    
992                    return GetterUtil.getLong(
993                            SessionClicks.get(
994                                    request, Staging.class.getName(),
995                                    getRecentLayoutSetBranchIdKey(layoutSetId)));
996            }
997    
998            @Override
999            public long getRecentLayoutSetBranchId(User user, long layoutSetId)
1000                    throws SystemException {
1001    
1002                    PortalPreferences portalPreferences = getPortalPreferences(user);
1003    
1004                    return GetterUtil.getLong(
1005                            portalPreferences.getValue(
1006                                    Staging.class.getName(),
1007                                    getRecentLayoutSetBranchIdKey(layoutSetId)));
1008            }
1009    
1010            @Override
1011            public String getSchedulerGroupName(String destinationName, long groupId) {
1012                    return destinationName.concat(StringPool.SLASH).concat(
1013                            String.valueOf(groupId));
1014            }
1015    
1016            @Override
1017            public String getStagedPortletId(String portletId) {
1018                    String key = portletId;
1019    
1020                    if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
1021                            return key;
1022                    }
1023    
1024                    return StagingConstants.STAGED_PORTLET.concat(portletId);
1025            }
1026    
1027            @Override
1028            public Map<String, String[]> getStagingParameters() {
1029                    Map<String, String[]> parameterMap =
1030                            new LinkedHashMap<String, String[]>();
1031    
1032                    parameterMap.put(
1033                            PortletDataHandlerKeys.CATEGORIES,
1034                            new String[] {Boolean.TRUE.toString()});
1035                    parameterMap.put(
1036                            PortletDataHandlerKeys.DATA_STRATEGY,
1037                            new String[] {
1038                                    PortletDataHandlerKeys.DATA_STRATEGY_MIRROR_OVERWRITE});
1039                    parameterMap.put(
1040                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1041                            new String[] {Boolean.TRUE.toString()});
1042                    parameterMap.put(
1043                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1044                            new String[] {Boolean.FALSE.toString()});
1045                    parameterMap.put(
1046                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
1047                            new String[] {Boolean.TRUE.toString()});
1048                    parameterMap.put(
1049                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1050                            new String[] {Boolean.FALSE.toString()});
1051                    parameterMap.put(
1052                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
1053                            new String[] {Boolean.FALSE.toString()});
1054                    parameterMap.put(
1055                            PortletDataHandlerKeys.LOGO,
1056                            new String[] {Boolean.FALSE.toString()});
1057                    parameterMap.put(
1058                            PortletDataHandlerKeys.PERMISSIONS,
1059                            new String[] {Boolean.TRUE.toString()});
1060                    parameterMap.put(
1061                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
1062                            new String[] {Boolean.TRUE.toString()});
1063                    parameterMap.put(
1064                            PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL,
1065                            new String[] {Boolean.TRUE.toString()});
1066                    parameterMap.put(
1067                            PortletDataHandlerKeys.PORTLET_DATA,
1068                            new String[] {Boolean.TRUE.toString()});
1069                    parameterMap.put(
1070                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
1071                            new String[] {Boolean.TRUE.toString()});
1072                    parameterMap.put(
1073                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
1074                            new String[] {Boolean.TRUE.toString()});
1075                    parameterMap.put(
1076                            PortletDataHandlerKeys.THEME_REFERENCE,
1077                            new String[] {Boolean.TRUE.toString()});
1078                    parameterMap.put(
1079                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1080                            new String[] {Boolean.TRUE.toString()});
1081                    parameterMap.put(
1082                            PortletDataHandlerKeys.USER_ID_STRATEGY,
1083                            new String[] {UserIdStrategy.CURRENT_USER_ID});
1084    
1085                    return parameterMap;
1086            }
1087    
1088            @Override
1089            public Map<String, String[]> getStagingParameters(
1090                    PortletRequest portletRequest) {
1091    
1092                    Map<String, String[]> parameterMap =
1093                            new LinkedHashMap<String, String[]>(
1094                                    portletRequest.getParameterMap());
1095    
1096                    if (!parameterMap.containsKey(PortletDataHandlerKeys.DATA_STRATEGY)) {
1097                            parameterMap.put(
1098                                    PortletDataHandlerKeys.DATA_STRATEGY,
1099                                    new String[] {
1100                                            PortletDataHandlerKeys.DATA_STRATEGY_MIRROR_OVERWRITE});
1101                    }
1102    
1103                    /*if (!parameterMap.containsKey(
1104                                    PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS)) {
1105    
1106                            parameterMap.put(
1107                                    PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1108                                    new String[] {Boolean.TRUE.toString()});
1109                    }*/
1110    
1111                    if (!parameterMap.containsKey(
1112                                    PortletDataHandlerKeys.DELETE_PORTLET_DATA)) {
1113    
1114                            parameterMap.put(
1115                                    PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1116                                    new String[] {Boolean.FALSE.toString()});
1117                    }
1118    
1119                    if (!parameterMap.containsKey(
1120                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED)) {
1121    
1122                            parameterMap.put(
1123                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1124                                    new String[] {Boolean.FALSE.toString()});
1125                    }
1126    
1127                    if (!parameterMap.containsKey(
1128                                    PortletDataHandlerKeys.LAYOUT_SET_SETTINGS)) {
1129    
1130                            parameterMap.put(
1131                                    PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
1132                                    new String[] {Boolean.FALSE.toString()});
1133                    }
1134    
1135                    if (!parameterMap.containsKey(PortletDataHandlerKeys.LOGO)) {
1136                            parameterMap.put(
1137                                    PortletDataHandlerKeys.LOGO,
1138                                    new String[] {Boolean.FALSE.toString()});
1139                    }
1140    
1141                    if (!parameterMap.containsKey(
1142                                    PortletDataHandlerKeys.PORTLET_CONFIGURATION)) {
1143    
1144                            parameterMap.put(
1145                                    PortletDataHandlerKeys.PORTLET_CONFIGURATION,
1146                                    new String[] {Boolean.TRUE.toString()});
1147                    }
1148    
1149                    if (!parameterMap.containsKey(PortletDataHandlerKeys.PORTLET_DATA)) {
1150                            parameterMap.put(
1151                                    PortletDataHandlerKeys.PORTLET_DATA,
1152                                    new String[] {Boolean.FALSE.toString()});
1153                    }
1154    
1155                    if (!parameterMap.containsKey(
1156                                    PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
1157    
1158                            parameterMap.put(
1159                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1160                                    new String[] {Boolean.FALSE.toString()});
1161                    }
1162    
1163                    if (!parameterMap.containsKey(PortletDataHandlerKeys.THEME_REFERENCE)) {
1164                            parameterMap.put(
1165                                    PortletDataHandlerKeys.THEME_REFERENCE,
1166                                    new String[] {Boolean.FALSE.toString()});
1167                    }
1168    
1169                    if (!parameterMap.containsKey(
1170                                    PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE)) {
1171    
1172                            parameterMap.put(
1173                                    PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1174                                    new String[] {Boolean.TRUE.toString()});
1175                    }
1176    
1177                    if (!parameterMap.containsKey(
1178                                    PortletDataHandlerKeys.USER_ID_STRATEGY)) {
1179    
1180                            parameterMap.put(
1181                                    PortletDataHandlerKeys.USER_ID_STRATEGY,
1182                                    new String[] {UserIdStrategy.CURRENT_USER_ID});
1183                    }
1184    
1185                    return parameterMap;
1186            }
1187    
1188            @Override
1189            public JSONArray getWarningMessagesJSONArray(
1190                    Locale locale, Map<String, MissingReference> missingReferences,
1191                    Map<String, Serializable> contextMap) {
1192    
1193                    JSONArray warningMessagesJSONArray = JSONFactoryUtil.createJSONArray();
1194    
1195                    for (String missingReferenceReferrerClassName :
1196                                    missingReferences.keySet()) {
1197    
1198                            MissingReference missingReference = missingReferences.get(
1199                                    missingReferenceReferrerClassName);
1200    
1201                            Map<String, String> referrers = missingReference.getReferrers();
1202    
1203                            JSONObject errorMessageJSONObject =
1204                                    JSONFactoryUtil.createJSONObject();
1205    
1206                            if (Validator.isNotNull(missingReference.getClassName())) {
1207                                    errorMessageJSONObject.put(
1208                                            "info",
1209                                            LanguageUtil.format(
1210                                                    locale,
1211                                                    "the-original-x-does-not-exist-in-the-current-" +
1212                                                            "environment",
1213                                                    ResourceActionsUtil.getModelResource(
1214                                                            locale, missingReference.getClassName())));
1215                            }
1216    
1217                            errorMessageJSONObject.put("size", referrers.size());
1218                            errorMessageJSONObject.put(
1219                                    "type",
1220                                    ResourceActionsUtil.getModelResource(
1221                                            locale, missingReferenceReferrerClassName));
1222    
1223                            warningMessagesJSONArray.put(errorMessageJSONObject);
1224                    }
1225    
1226                    return warningMessagesJSONArray;
1227            }
1228    
1229            @Override
1230            public WorkflowTask getWorkflowTask(
1231                            long userId, LayoutRevision layoutRevision)
1232                    throws PortalException, SystemException {
1233    
1234                    WorkflowInstanceLink workflowInstanceLink =
1235                            WorkflowInstanceLinkLocalServiceUtil.fetchWorkflowInstanceLink(
1236                                    layoutRevision.getCompanyId(), layoutRevision.getGroupId(),
1237                                    LayoutRevision.class.getName(),
1238                                    layoutRevision.getLayoutRevisionId());
1239    
1240                    if (workflowInstanceLink == null) {
1241                            return null;
1242                    }
1243    
1244                    List<WorkflowTask> workflowTasks =
1245                            WorkflowTaskManagerUtil.getWorkflowTasksByWorkflowInstance(
1246                                    layoutRevision.getCompanyId(), userId,
1247                                    workflowInstanceLink.getWorkflowInstanceId(), false, 0, 1,
1248                                    null);
1249    
1250                    if (!workflowTasks.isEmpty()) {
1251                            return workflowTasks.get(0);
1252                    }
1253    
1254                    return null;
1255            }
1256    
1257            @Override
1258            public boolean hasWorkflowTask(long userId, LayoutRevision layoutRevision)
1259                    throws PortalException, SystemException {
1260    
1261                    WorkflowTask workflowTask = getWorkflowTask(userId, layoutRevision);
1262    
1263                    if (workflowTask != null) {
1264                            return true;
1265                    }
1266    
1267                    return false;
1268            }
1269    
1270            @Override
1271            public boolean isIncomplete(Layout layout, long layoutSetBranchId) {
1272                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
1273                            layout);
1274    
1275                    if (layoutRevision == null) {
1276                            try {
1277                                    layoutRevision =
1278                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
1279                                                    layoutSetBranchId, layout.getPlid(), true);
1280    
1281                                    return false;
1282                            }
1283                            catch (Exception e) {
1284                            }
1285                    }
1286    
1287                    try {
1288                            layoutRevision = LayoutRevisionLocalServiceUtil.getLayoutRevision(
1289                                    layoutSetBranchId, layout.getPlid(), false);
1290                    }
1291                    catch (Exception e) {
1292                    }
1293    
1294                    if ((layoutRevision == null) ||
1295                            (layoutRevision.getStatus() ==
1296                                    WorkflowConstants.STATUS_INCOMPLETE)) {
1297    
1298                            return true;
1299                    }
1300    
1301                    return false;
1302            }
1303    
1304            @Override
1305            public void lockGroup(long userId, long groupId) throws Exception {
1306                    if (!PropsValues.STAGING_LOCK_ENABLED) {
1307                            return;
1308                    }
1309    
1310                    if (LockLocalServiceUtil.isLocked(Staging.class.getName(), groupId)) {
1311                            Lock lock = LockLocalServiceUtil.getLock(
1312                                    Staging.class.getName(), groupId);
1313    
1314                            throw new DuplicateLockException(lock);
1315                    }
1316    
1317                    LockLocalServiceUtil.lock(
1318                            userId, Staging.class.getName(), String.valueOf(groupId),
1319                            StagingImpl.class.getName(), false,
1320                            StagingConstants.LOCK_EXPIRATION_TIME);
1321            }
1322    
1323            @Override
1324            public void publishLayout(
1325                            long userId, long plid, long liveGroupId, boolean includeChildren)
1326                    throws Exception {
1327    
1328                    Map<String, String[]> parameterMap = getStagingParameters();
1329    
1330                    parameterMap.put(
1331                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1332                            new String[] {Boolean.FALSE.toString()});
1333    
1334                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1335    
1336                    List<Layout> layouts = new ArrayList<Layout>();
1337    
1338                    layouts.add(layout);
1339    
1340                    layouts.addAll(getMissingParentLayouts(layout, liveGroupId));
1341    
1342                    if (includeChildren) {
1343                            layouts.addAll(layout.getAllChildren());
1344                    }
1345    
1346                    long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);
1347    
1348                    publishLayouts(
1349                            userId, layout.getGroupId(), liveGroupId, layout.isPrivateLayout(),
1350                            layoutIds, parameterMap, null, null);
1351            }
1352    
1353            @Override
1354            public void publishLayouts(
1355                            long userId, long sourceGroupId, long targetGroupId,
1356                            boolean privateLayout, long[] layoutIds,
1357                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1358                    throws PortalException, SystemException {
1359    
1360                    parameterMap.put(
1361                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
1362                            new String[] {Boolean.TRUE.toString()});
1363    
1364                    Map<String, Serializable> taskContextMap =
1365                            BackgroundTaskContextMapFactory.buildTaskContextMap(
1366                                    userId, sourceGroupId, privateLayout, layoutIds, parameterMap,
1367                                    Constants.PUBLISH_TO_LIVE, startDate, endDate,
1368                                    StringPool.BLANK);
1369    
1370                    taskContextMap.put("sourceGroupId", sourceGroupId);
1371                    taskContextMap.put("targetGroupId", targetGroupId);
1372    
1373                    BackgroundTaskLocalServiceUtil.addBackgroundTask(
1374                            userId, sourceGroupId, StringPool.BLANK, null,
1375                            LayoutStagingBackgroundTaskExecutor.class, taskContextMap,
1376                            new ServiceContext());
1377            }
1378    
1379            @Override
1380            public void publishLayouts(
1381                            long userId, long sourceGroupId, long targetGroupId,
1382                            boolean privateLayout, Map<Long, Boolean> layoutIdMap,
1383                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1384                    throws PortalException, SystemException {
1385    
1386                    List<Layout> layouts = new ArrayList<Layout>();
1387    
1388                    for (Map.Entry<Long, Boolean> entry : layoutIdMap.entrySet()) {
1389                            long plid = GetterUtil.getLong(String.valueOf(entry.getKey()));
1390                            boolean includeChildren = entry.getValue();
1391    
1392                            Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1393    
1394                            if (!layouts.contains(layout)) {
1395                                    layouts.add(layout);
1396                            }
1397    
1398                            List<Layout> parentLayouts = getMissingParentLayouts(
1399                                    layout, targetGroupId);
1400    
1401                            for (Layout parentLayout : parentLayouts) {
1402                                    if (!layouts.contains(parentLayout)) {
1403                                            layouts.add(parentLayout);
1404                                    }
1405                            }
1406    
1407                            if (includeChildren) {
1408                                    for (Layout childLayout : layout.getAllChildren()) {
1409                                            if (!layouts.contains(childLayout)) {
1410                                                    layouts.add(childLayout);
1411                                            }
1412                                    }
1413                            }
1414                    }
1415    
1416                    long[] layoutIds = ExportImportHelperUtil.getLayoutIds(layouts);
1417    
1418                    publishLayouts(
1419                            userId, sourceGroupId, targetGroupId, privateLayout, layoutIds,
1420                            parameterMap, startDate, endDate);
1421            }
1422    
1423            @Override
1424            public void publishLayouts(
1425                            long userId, long sourceGroupId, long targetGroupId,
1426                            boolean privateLayout, Map<String, String[]> parameterMap,
1427                            Date startDate, Date endDate)
1428                    throws PortalException, SystemException {
1429    
1430                    publishLayouts(
1431                            userId, sourceGroupId, targetGroupId, privateLayout, (long[])null,
1432                            parameterMap, startDate, endDate);
1433            }
1434    
1435            @Override
1436            public void publishToLive(PortletRequest portletRequest) throws Exception {
1437                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1438    
1439                    Group liveGroup = GroupLocalServiceUtil.getGroup(groupId);
1440    
1441                    Map<String, String[]> parameterMap = getStagingParameters(
1442                            portletRequest);
1443    
1444                    if (liveGroup.isStaged()) {
1445                            if (liveGroup.isStagedRemotely()) {
1446                                    publishToRemote(portletRequest);
1447                            }
1448                            else {
1449                                    Group stagingGroup = liveGroup.getStagingGroup();
1450    
1451                                    publishLayouts(
1452                                            portletRequest, stagingGroup.getGroupId(), groupId,
1453                                            parameterMap, false);
1454                            }
1455                    }
1456            }
1457    
1458            @Override
1459            public void publishToLive(PortletRequest portletRequest, Portlet portlet)
1460                    throws Exception {
1461    
1462                    long plid = ParamUtil.getLong(portletRequest, "plid");
1463    
1464                    Layout sourceLayout = LayoutLocalServiceUtil.getLayout(plid);
1465    
1466                    Group stagingGroup = null;
1467                    Group liveGroup = null;
1468    
1469                    Layout targetLayout = null;
1470    
1471                    long scopeGroupId = PortalUtil.getScopeGroupId(portletRequest);
1472    
1473                    if (sourceLayout.isTypeControlPanel()) {
1474                            stagingGroup = GroupLocalServiceUtil.fetchGroup(scopeGroupId);
1475                            liveGroup = stagingGroup.getLiveGroup();
1476    
1477                            targetLayout = sourceLayout;
1478                    }
1479                    else if (sourceLayout.hasScopeGroup() &&
1480                                     (sourceLayout.getScopeGroup().getGroupId() == scopeGroupId)) {
1481    
1482                            stagingGroup = sourceLayout.getScopeGroup();
1483                            liveGroup = stagingGroup.getLiveGroup();
1484    
1485                            targetLayout = LayoutLocalServiceUtil.getLayout(
1486                                    liveGroup.getClassPK());
1487                    }
1488                    else {
1489                            stagingGroup = sourceLayout.getGroup();
1490                            liveGroup = stagingGroup.getLiveGroup();
1491    
1492                            targetLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
1493                                    sourceLayout.getUuid(), liveGroup.getGroupId(),
1494                                    sourceLayout.isPrivateLayout());
1495                    }
1496    
1497                    copyPortlet(
1498                            portletRequest, stagingGroup.getGroupId(), liveGroup.getGroupId(),
1499                            sourceLayout.getPlid(), targetLayout.getPlid(),
1500                            portlet.getPortletId());
1501            }
1502    
1503            @Override
1504            public void publishToRemote(PortletRequest portletRequest)
1505                    throws Exception {
1506    
1507                    publishToRemote(portletRequest, false);
1508            }
1509    
1510            @Override
1511            public void scheduleCopyFromLive(PortletRequest portletRequest)
1512                    throws Exception {
1513    
1514                    long stagingGroupId = ParamUtil.getLong(
1515                            portletRequest, "stagingGroupId");
1516    
1517                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1518    
1519                    long liveGroupId = stagingGroup.getLiveGroupId();
1520    
1521                    Map<String, String[]> parameterMap = getStagingParameters(
1522                            portletRequest);
1523    
1524                    publishLayouts(
1525                            portletRequest, liveGroupId, stagingGroupId, parameterMap, true);
1526            }
1527    
1528            @Override
1529            public void schedulePublishToLive(PortletRequest portletRequest)
1530                    throws Exception {
1531    
1532                    long stagingGroupId = ParamUtil.getLong(
1533                            portletRequest, "stagingGroupId");
1534    
1535                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1536    
1537                    long liveGroupId = stagingGroup.getLiveGroupId();
1538    
1539                    Map<String, String[]> parameterMap = getStagingParameters(
1540                            portletRequest);
1541    
1542                    publishLayouts(
1543                            portletRequest, stagingGroupId, liveGroupId, parameterMap, true);
1544            }
1545    
1546            @Override
1547            public void schedulePublishToRemote(PortletRequest portletRequest)
1548                    throws Exception {
1549    
1550                    publishToRemote(portletRequest, true);
1551            }
1552    
1553            @Override
1554            public void setRecentLayoutBranchId(
1555                            HttpServletRequest request, long layoutSetBranchId, long plid,
1556                            long layoutBranchId)
1557                    throws SystemException {
1558    
1559                    PortalPreferences portalPreferences =
1560                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1561    
1562                    setRecentLayoutBranchId(
1563                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1564            }
1565    
1566            @Override
1567            public void setRecentLayoutBranchId(
1568                            User user, long layoutSetBranchId, long plid, long layoutBranchId)
1569                    throws SystemException {
1570    
1571                    PortalPreferences portalPreferences = getPortalPreferences(user);
1572    
1573                    setRecentLayoutBranchId(
1574                            portalPreferences, layoutSetBranchId, plid, layoutBranchId);
1575            }
1576    
1577            @Override
1578            public void setRecentLayoutRevisionId(
1579                            HttpServletRequest request, long layoutSetBranchId, long plid,
1580                            long layoutRevisionId)
1581                    throws SystemException {
1582    
1583                    PortalPreferences portalPreferences =
1584                            PortletPreferencesFactoryUtil.getPortalPreferences(request);
1585    
1586                    setRecentLayoutRevisionId(
1587                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1588            }
1589    
1590            @Override
1591            public void setRecentLayoutRevisionId(
1592                            User user, long layoutSetBranchId, long plid, long layoutRevisionId)
1593                    throws SystemException {
1594    
1595                    PortalPreferences portalPreferences = getPortalPreferences(user);
1596    
1597                    setRecentLayoutRevisionId(
1598                            portalPreferences, layoutSetBranchId, plid, layoutRevisionId);
1599            }
1600    
1601            @Override
1602            public void setRecentLayoutSetBranchId(
1603                    HttpServletRequest request, long layoutSetId, long layoutSetBranchId) {
1604    
1605                    SessionClicks.put(
1606                            request, Staging.class.getName(),
1607                            getRecentLayoutSetBranchIdKey(layoutSetId),
1608                            String.valueOf(layoutSetBranchId));
1609            }
1610    
1611            @Override
1612            public void setRecentLayoutSetBranchId(
1613                            User user, long layoutSetId, long layoutSetBranchId)
1614                    throws SystemException {
1615    
1616                    PortalPreferences portalPreferences = getPortalPreferences(user);
1617    
1618                    portalPreferences.setValue(
1619                            Staging.class.getName(), getRecentLayoutSetBranchIdKey(layoutSetId),
1620                            String.valueOf(layoutSetBranchId));
1621            }
1622    
1623            @Override
1624            public void unlockGroup(long groupId) throws SystemException {
1625                    if (!PropsValues.STAGING_LOCK_ENABLED) {
1626                            return;
1627                    }
1628    
1629                    LockLocalServiceUtil.unlock(Staging.class.getName(), groupId);
1630            }
1631    
1632            @Override
1633            public void unscheduleCopyFromLive(PortletRequest portletRequest)
1634                    throws Exception {
1635    
1636                    long stagingGroupId = ParamUtil.getLong(
1637                            portletRequest, "stagingGroupId");
1638    
1639                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1640                    String groupName = getSchedulerGroupName(
1641                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
1642    
1643                    LayoutServiceUtil.unschedulePublishToLive(
1644                            stagingGroupId, jobName, groupName);
1645            }
1646    
1647            @Override
1648            public void unschedulePublishToLive(PortletRequest portletRequest)
1649                    throws Exception {
1650    
1651                    long stagingGroupId = ParamUtil.getLong(
1652                            portletRequest, "stagingGroupId");
1653    
1654                    Group stagingGroup = GroupLocalServiceUtil.getGroup(stagingGroupId);
1655    
1656                    long liveGroupId = stagingGroup.getLiveGroupId();
1657    
1658                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1659                    String groupName = getSchedulerGroupName(
1660                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
1661    
1662                    LayoutServiceUtil.unschedulePublishToLive(
1663                            liveGroupId, jobName, groupName);
1664            }
1665    
1666            @Override
1667            public void unschedulePublishToRemote(PortletRequest portletRequest)
1668                    throws Exception {
1669    
1670                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
1671    
1672                    String jobName = ParamUtil.getString(portletRequest, "jobName");
1673                    String groupName = getSchedulerGroupName(
1674                            DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
1675    
1676                    LayoutServiceUtil.unschedulePublishToRemote(
1677                            groupId, jobName, groupName);
1678            }
1679    
1680            @Override
1681            public void updateLastImportSettings(
1682                            Element layoutElement, Layout layout,
1683                            PortletDataContext portletDataContext)
1684                    throws Exception {
1685    
1686                    Map<String, String[]> parameterMap =
1687                            portletDataContext.getParameterMap();
1688    
1689                    String cmd = MapUtil.getString(parameterMap, Constants.CMD);
1690    
1691                    if (!cmd.equals("publish_to_live")) {
1692                            return;
1693                    }
1694    
1695                    UnicodeProperties typeSettingsProperties =
1696                            layout.getTypeSettingsProperties();
1697    
1698                    typeSettingsProperties.setProperty(
1699                            "last-import-date", String.valueOf(System.currentTimeMillis()));
1700    
1701                    String layoutRevisionId = GetterUtil.getString(
1702                            layoutElement.attributeValue("layout-revision-id"));
1703    
1704                    typeSettingsProperties.setProperty(
1705                            "last-import-layout-revision-id", layoutRevisionId);
1706    
1707                    String layoutSetBranchId = MapUtil.getString(
1708                            parameterMap, "layoutSetBranchId");
1709    
1710                    typeSettingsProperties.setProperty(
1711                            "last-import-layout-set-branch-id", layoutSetBranchId);
1712    
1713                    String layoutSetBranchName = MapUtil.getString(
1714                            parameterMap, "layoutSetBranchName");
1715    
1716                    typeSettingsProperties.setProperty(
1717                            "last-import-layout-set-branch-name", layoutSetBranchName);
1718    
1719                    String lastImportUserName = MapUtil.getString(
1720                            parameterMap, "lastImportUserName");
1721    
1722                    typeSettingsProperties.setProperty(
1723                            "last-import-user-name", lastImportUserName);
1724    
1725                    String lastImportUserUuid = MapUtil.getString(
1726                            parameterMap, "lastImportUserUuid");
1727    
1728                    typeSettingsProperties.setProperty(
1729                            "last-import-user-uuid", lastImportUserUuid);
1730    
1731                    String layoutBranchId = GetterUtil.getString(
1732                            layoutElement.attributeValue("layout-branch-id"));
1733    
1734                    typeSettingsProperties.setProperty(
1735                            "last-import-layout-branch-id", layoutBranchId);
1736    
1737                    String layoutBranchName = GetterUtil.getString(
1738                            layoutElement.attributeValue("layout-branch-name"));
1739    
1740                    typeSettingsProperties.setProperty(
1741                            "last-import-layout-branch-name", layoutBranchName);
1742    
1743                    layout.setTypeSettingsProperties(typeSettingsProperties);
1744            }
1745    
1746            @Override
1747            public void updateLastPublishDate(
1748                            long groupId, boolean privateLayout, Date lastPublishDate)
1749                    throws Exception {
1750    
1751                    if (lastPublishDate == null) {
1752                            lastPublishDate = new Date();
1753                    }
1754    
1755                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
1756                            groupId, privateLayout);
1757    
1758                    UnicodeProperties settingsProperties =
1759                            layoutSet.getSettingsProperties();
1760    
1761                    settingsProperties.setProperty(
1762                            "last-publish-date", String.valueOf(lastPublishDate.getTime()));
1763    
1764                    LayoutSetLocalServiceUtil.updateSettings(
1765                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
1766                            settingsProperties.toString());
1767            }
1768    
1769            @Override
1770            public void updateLastPublishDate(
1771                            String portletId, PortletPreferences portletPreferences,
1772                            Date lastPublishDate)
1773                    throws Exception {
1774    
1775                    if (lastPublishDate == null) {
1776                            lastPublishDate = new Date();
1777                    }
1778    
1779                    try {
1780                            portletPreferences.setValue(
1781                                    "last-publish-date", String.valueOf(lastPublishDate.getTime()));
1782    
1783                            portletPreferences.store();
1784                    }
1785                    catch (UnsupportedOperationException uoe) {
1786                            if (_log.isDebugEnabled()) {
1787                                    _log.debug(
1788                                            "Not updating the portlet setup for " + portletId +
1789                                                    " because no setup was returned for the current " +
1790                                                            "page");
1791                            }
1792                    }
1793                    catch (Exception e) {
1794                            _log.error(e, e);
1795                    }
1796            }
1797    
1798            @Override
1799            public void updateStaging(PortletRequest portletRequest, Group liveGroup)
1800                    throws Exception {
1801    
1802                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
1803                            WebKeys.THEME_DISPLAY);
1804    
1805                    PermissionChecker permissionChecker =
1806                            themeDisplay.getPermissionChecker();
1807    
1808                    long userId = permissionChecker.getUserId();
1809    
1810                    if (!GroupPermissionUtil.contains(
1811                                    permissionChecker, liveGroup.getGroupId(),
1812                                    ActionKeys.MANAGE_STAGING)) {
1813    
1814                            return;
1815                    }
1816    
1817                    int stagingType = getStagingType(portletRequest, liveGroup);
1818    
1819                    boolean branchingPublic = getBoolean(
1820                            portletRequest, liveGroup, "branchingPublic");
1821                    boolean branchingPrivate = getBoolean(
1822                            portletRequest, liveGroup, "branchingPrivate");
1823    
1824                    ServiceContext serviceContext =
1825                            ServiceContextThreadLocal.getServiceContext();
1826    
1827                    if (stagingType == StagingConstants.TYPE_NOT_STAGED) {
1828                            if (liveGroup.hasStagingGroup() || liveGroup.isStagedRemotely()) {
1829                                    StagingLocalServiceUtil.disableStaging(
1830                                            portletRequest, liveGroup, serviceContext);
1831                            }
1832                    }
1833                    else if (stagingType == StagingConstants.TYPE_LOCAL_STAGING) {
1834                            StagingLocalServiceUtil.enableLocalStaging(
1835                                    userId, liveGroup, branchingPublic, branchingPrivate,
1836                                    serviceContext);
1837                    }
1838                    else if (stagingType == StagingConstants.TYPE_REMOTE_STAGING) {
1839                            String remoteAddress = getString(
1840                                    portletRequest, liveGroup, "remoteAddress");
1841    
1842                            remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
1843    
1844                            int remotePort = getInteger(
1845                                    portletRequest, liveGroup, "remotePort");
1846                            String remotePathContext = getString(
1847                                    portletRequest, liveGroup, "remotePathContext");
1848                            boolean secureConnection = getBoolean(
1849                                    portletRequest, liveGroup, "secureConnection");
1850                            long remoteGroupId = getLong(
1851                                    portletRequest, liveGroup, "remoteGroupId");
1852    
1853                            StagingLocalServiceUtil.enableRemoteStaging(
1854                                    userId, liveGroup, branchingPublic, branchingPrivate,
1855                                    remoteAddress, remotePort, remotePathContext, secureConnection,
1856                                    remoteGroupId, serviceContext);
1857                    }
1858            }
1859    
1860            @Override
1861            public void validateRemote(
1862                            String remoteAddress, int remotePort, String remotePathContext,
1863                            boolean secureConnection, long remoteGroupId)
1864                    throws PortalException {
1865    
1866                    RemoteOptionsException roe = null;
1867    
1868                    if (!Validator.isDomain(remoteAddress) &&
1869                            !Validator.isIPAddress(remoteAddress)) {
1870    
1871                            roe = new RemoteOptionsException(
1872                                    RemoteOptionsException.REMOTE_ADDRESS);
1873    
1874                            roe.setRemoteAddress(remoteAddress);
1875    
1876                            throw roe;
1877                    }
1878    
1879                    if ((remotePort < 1) || (remotePort > 65535)) {
1880                            roe = new RemoteOptionsException(
1881                                    RemoteOptionsException.REMOTE_PORT);
1882    
1883                            roe.setRemotePort(remotePort);
1884    
1885                            throw roe;
1886                    }
1887    
1888                    if (Validator.isNotNull(remotePathContext) &&
1889                            (!remotePathContext.startsWith(StringPool.FORWARD_SLASH) ||
1890                             remotePathContext.endsWith(StringPool.FORWARD_SLASH))) {
1891    
1892                            roe = new RemoteOptionsException(
1893                                    RemoteOptionsException.REMOTE_PATH_CONTEXT);
1894    
1895                            roe.setRemotePathContext(remotePathContext);
1896    
1897                            throw roe;
1898                    }
1899    
1900                    if (remoteGroupId <= 0) {
1901                            roe = new RemoteOptionsException(
1902                                    RemoteOptionsException.REMOTE_GROUP_ID);
1903    
1904                            roe.setRemoteGroupId(remoteGroupId);
1905    
1906                            throw roe;
1907                    }
1908    
1909                    PermissionChecker permissionChecker =
1910                            PermissionThreadLocal.getPermissionChecker();
1911    
1912                    User user = permissionChecker.getUser();
1913    
1914                    String remoteURL = buildRemoteURL(
1915                            remoteAddress, remotePort, remotePathContext, secureConnection,
1916                            GroupConstants.DEFAULT_LIVE_GROUP_ID, false);
1917    
1918                    HttpPrincipal httpPrincipal = new HttpPrincipal(
1919                            remoteURL, user.getEmailAddress(), user.getPassword(),
1920                            user.getPasswordEncrypted());
1921    
1922                    // Ping remote host and verify that the group exists in the same company
1923                    // as the remote user
1924    
1925                    try {
1926                            GroupServiceHttp.checkRemoteStagingGroup(
1927                                    httpPrincipal, remoteGroupId);
1928                    }
1929                    catch (NoSuchGroupException nsge) {
1930                            RemoteExportException ree = new RemoteExportException(
1931                                    RemoteExportException.NO_GROUP);
1932    
1933                            ree.setGroupId(remoteGroupId);
1934    
1935                            throw ree;
1936                    }
1937                    catch (PrincipalException pe) {
1938                            RemoteExportException ree = new RemoteExportException(
1939                                    RemoteExportException.NO_PERMISSIONS);
1940    
1941                            ree.setGroupId(remoteGroupId);
1942    
1943                            throw ree;
1944                    }
1945                    catch (RemoteAuthException rae) {
1946                            rae.setURL(remoteURL);
1947    
1948                            throw rae;
1949                    }
1950                    catch (SystemException se) {
1951                            RemoteExportException ree = new RemoteExportException(
1952                                    RemoteExportException.BAD_CONNECTION, se.getMessage());
1953    
1954                            ree.setURL(remoteURL);
1955    
1956                            throw ree;
1957                    }
1958            }
1959    
1960            protected void deleteRecentLayoutRevisionId(
1961                    PortalPreferences portalPreferences, long layoutSetBranchId,
1962                    long plid) {
1963    
1964                    portalPreferences.setValue(
1965                            Staging.class.getName(),
1966                            getRecentLayoutRevisionIdKey(layoutSetBranchId, plid), null);
1967            }
1968    
1969            protected boolean getBoolean(
1970                    PortletRequest portletRequest, Group group, String param) {
1971    
1972                    return ParamUtil.getBoolean(
1973                            portletRequest, param,
1974                            GetterUtil.getBoolean(group.getTypeSettingsProperty(param)));
1975            }
1976    
1977            protected int getInteger(
1978                    PortletRequest portletRequest, Group group, String param) {
1979    
1980                    return ParamUtil.getInteger(
1981                            portletRequest, param,
1982                            GetterUtil.getInteger(group.getTypeSettingsProperty(param)));
1983            }
1984    
1985            protected long getLong(
1986                    PortletRequest portletRequest, Group group, String param) {
1987    
1988                    return ParamUtil.getLong(
1989                            portletRequest, param,
1990                            GetterUtil.getLong(group.getTypeSettingsProperty(param)));
1991            }
1992    
1993            protected PortalPreferences getPortalPreferences(User user)
1994                    throws SystemException {
1995    
1996                    boolean signedIn = !user.isDefaultUser();
1997    
1998                    PortalPreferences portalPreferences =
1999                            PortletPreferencesFactoryUtil.getPortalPreferences(
2000                                    user.getUserId(), signedIn);
2001    
2002                    return portalPreferences;
2003            }
2004    
2005            protected long getRecentLayoutBranchId(
2006                    PortalPreferences portalPreferences, long layoutSetBranchId,
2007                    long plid) {
2008    
2009                    return GetterUtil.getLong(
2010                            portalPreferences.getValue(
2011                                    Staging.class.getName(),
2012                                    getRecentLayoutBranchIdKey(layoutSetBranchId, plid)));
2013            }
2014    
2015            protected String getRecentLayoutBranchIdKey(
2016                    long layoutSetBranchId, long plid) {
2017    
2018                    StringBundler sb = new StringBundler(4);
2019    
2020                    sb.append("layoutBranchId-");
2021                    sb.append(layoutSetBranchId);
2022                    sb.append(StringPool.DASH);
2023                    sb.append(plid);
2024    
2025                    return sb.toString();
2026            }
2027    
2028            protected long getRecentLayoutRevisionId(
2029                            PortalPreferences portalPreferences, long layoutSetBranchId,
2030                            long plid)
2031                    throws PortalException, SystemException {
2032    
2033                    long layoutRevisionId = GetterUtil.getLong(
2034                            portalPreferences.getValue(
2035                                    Staging.class.getName(),
2036                                    getRecentLayoutRevisionIdKey(layoutSetBranchId, plid)));
2037    
2038                    if (layoutRevisionId > 0) {
2039                            return layoutRevisionId;
2040                    }
2041    
2042                    long layoutBranchId = getRecentLayoutBranchId(
2043                            portalPreferences, layoutSetBranchId, plid);
2044    
2045                    if (layoutBranchId > 0) {
2046                            try {
2047                                    LayoutBranchLocalServiceUtil.getLayoutBranch(layoutBranchId);
2048                            }
2049                            catch (NoSuchLayoutBranchException nslbe) {
2050                                    LayoutBranch layoutBranch =
2051                                            LayoutBranchLocalServiceUtil.getMasterLayoutBranch(
2052                                                    layoutSetBranchId, plid);
2053    
2054                                    layoutBranchId = layoutBranch.getLayoutBranchId();
2055                            }
2056                    }
2057    
2058                    if (layoutBranchId > 0) {
2059                            try {
2060                                    LayoutRevision layoutRevision =
2061                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
2062                                                    layoutSetBranchId, layoutBranchId, plid);
2063    
2064                                    if (layoutRevision != null) {
2065                                            layoutRevisionId = layoutRevision.getLayoutRevisionId();
2066                                    }
2067                            }
2068                            catch (NoSuchLayoutRevisionException nslre) {
2069                            }
2070                    }
2071    
2072                    return layoutRevisionId;
2073            }
2074    
2075            protected String getRecentLayoutRevisionIdKey(
2076                    long layoutSetBranchId, long plid) {
2077    
2078                    StringBundler sb = new StringBundler(4);
2079    
2080                    sb.append("layoutRevisionId-");
2081                    sb.append(layoutSetBranchId);
2082                    sb.append(StringPool.DASH);
2083                    sb.append(plid);
2084    
2085                    return sb.toString();
2086            }
2087    
2088            protected String getRecentLayoutSetBranchIdKey(long layoutSetId) {
2089                    return "layoutSetBranchId_" + layoutSetId;
2090            }
2091    
2092            protected int getStagingType(
2093                    PortletRequest portletRequest, Group liveGroup) {
2094    
2095                    String stagingType = portletRequest.getParameter("stagingType");
2096    
2097                    if (stagingType != null) {
2098                            return GetterUtil.getInteger(stagingType);
2099                    }
2100    
2101                    if (liveGroup.isStagedRemotely()) {
2102                            return StagingConstants.TYPE_REMOTE_STAGING;
2103                    }
2104    
2105                    if (liveGroup.hasStagingGroup()) {
2106                            return StagingConstants.TYPE_LOCAL_STAGING;
2107                    }
2108    
2109                    return StagingConstants.TYPE_NOT_STAGED;
2110            }
2111    
2112            protected String getString(
2113                    PortletRequest portletRequest, Group group, String param) {
2114    
2115                    return ParamUtil.getString(
2116                            portletRequest, param,
2117                            GetterUtil.getString(group.getTypeSettingsProperty(param)));
2118            }
2119    
2120            protected void publishLayouts(
2121                            PortletRequest portletRequest, long sourceGroupId,
2122                            long targetGroupId, Map<String, String[]> parameterMap,
2123                            boolean schedule)
2124                    throws Exception {
2125    
2126                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
2127                            WebKeys.THEME_DISPLAY);
2128    
2129                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
2130    
2131                    boolean privateLayout = true;
2132    
2133                    if (tabs1.equals("public-pages")) {
2134                            privateLayout = false;
2135                    }
2136    
2137                    String scope = ParamUtil.getString(portletRequest, "scope");
2138    
2139                    Map<Long, Boolean> layoutIdMap = new LinkedHashMap<Long, Boolean>();
2140    
2141                    if (scope.equals("selected-pages")) {
2142                            layoutIdMap = ExportImportHelperUtil.getLayoutIdMap(portletRequest);
2143                    }
2144    
2145                    DateRange dateRange = ExportImportHelperUtil.getDateRange(
2146                            portletRequest, sourceGroupId, privateLayout, 0, null,
2147                            "fromLastPublishDate");
2148    
2149                    if (schedule) {
2150                            String groupName = getSchedulerGroupName(
2151                                    DestinationNames.LAYOUTS_LOCAL_PUBLISHER, targetGroupId);
2152    
2153                            int recurrenceType = ParamUtil.getInteger(
2154                                    portletRequest, "recurrenceType");
2155    
2156                            Calendar startCalendar = ExportImportHelperUtil.getCalendar(
2157                                    portletRequest, "schedulerStartDate", true);
2158    
2159                            String cronText = SchedulerEngineHelperUtil.getCronText(
2160                                    portletRequest, startCalendar, true, recurrenceType);
2161    
2162                            Date schedulerEndDate = null;
2163    
2164                            int endDateType = ParamUtil.getInteger(
2165                                    portletRequest, "endDateType");
2166    
2167                            if (endDateType == 1) {
2168                                    Calendar endCalendar = ExportImportHelperUtil.getCalendar(
2169                                            portletRequest, "schedulerEndDate", true);
2170    
2171                                    schedulerEndDate = endCalendar.getTime();
2172                            }
2173    
2174                            String description = ParamUtil.getString(
2175                                    portletRequest, "description");
2176    
2177                            LayoutServiceUtil.schedulePublishToLive(
2178                                    sourceGroupId, targetGroupId, privateLayout, layoutIdMap,
2179                                    parameterMap, scope, dateRange.getStartDate(),
2180                                    dateRange.getEndDate(), groupName, cronText,
2181                                    startCalendar.getTime(), schedulerEndDate, description);
2182                    }
2183                    else {
2184                            MessageStatus messageStatus = new MessageStatus();
2185    
2186                            messageStatus.startTimer();
2187    
2188                            String command =
2189                                    LayoutsLocalPublisherRequest.COMMAND_SELECTED_PAGES;
2190    
2191                            try {
2192                                    if (scope.equals("all-pages")) {
2193                                            command = LayoutsLocalPublisherRequest.COMMAND_ALL_PAGES;
2194    
2195                                            publishLayouts(
2196                                                    themeDisplay.getUserId(), sourceGroupId, targetGroupId,
2197                                                    privateLayout, parameterMap, dateRange.getStartDate(),
2198                                                    dateRange.getEndDate());
2199                                    }
2200                                    else {
2201                                            publishLayouts(
2202                                                    themeDisplay.getUserId(), sourceGroupId, targetGroupId,
2203                                                    privateLayout, layoutIdMap, parameterMap,
2204                                                    dateRange.getStartDate(), dateRange.getEndDate());
2205                                    }
2206                            }
2207                            catch (Exception e) {
2208                                    messageStatus.setException(e);
2209    
2210                                    throw e;
2211                            }
2212                            finally {
2213                                    messageStatus.stopTimer();
2214    
2215                                    LayoutsLocalPublisherRequest publisherRequest =
2216                                            new LayoutsLocalPublisherRequest(
2217                                                    command, themeDisplay.getUserId(), sourceGroupId,
2218                                                    targetGroupId, privateLayout, layoutIdMap, parameterMap,
2219                                                    dateRange.getStartDate(), dateRange.getEndDate());
2220    
2221                                    messageStatus.setPayload(publisherRequest);
2222    
2223                                    MessageBusUtil.sendMessage(
2224                                            DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
2225                            }
2226                    }
2227            }
2228    
2229            protected void publishToRemote(
2230                            PortletRequest portletRequest, boolean schedule)
2231                    throws Exception {
2232    
2233                    ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
2234                            WebKeys.THEME_DISPLAY);
2235    
2236                    String tabs1 = ParamUtil.getString(portletRequest, "tabs1");
2237    
2238                    long groupId = ParamUtil.getLong(portletRequest, "groupId");
2239    
2240                    boolean privateLayout = true;
2241    
2242                    if (tabs1.equals("public-pages")) {
2243                            privateLayout = false;
2244                    }
2245    
2246                    String scope = ParamUtil.getString(portletRequest, "scope");
2247    
2248                    if (Validator.isNull(scope)) {
2249                            scope = "all-pages";
2250                    }
2251    
2252                    Map<Long, Boolean> layoutIdMap = null;
2253    
2254                    if (scope.equals("selected-pages")) {
2255                            layoutIdMap = ExportImportHelperUtil.getLayoutIdMap(portletRequest);
2256                    }
2257    
2258                    Map<String, String[]> parameterMap = getStagingParameters(
2259                            portletRequest);
2260    
2261                    parameterMap.put(
2262                            PortletDataHandlerKeys.PUBLISH_TO_REMOTE,
2263                            new String[] {Boolean.TRUE.toString()});
2264    
2265                    Group group = GroupLocalServiceUtil.getGroup(groupId);
2266    
2267                    UnicodeProperties groupTypeSettingsProperties =
2268                            group.getTypeSettingsProperties();
2269    
2270                    String remoteAddress = ParamUtil.getString(
2271                            portletRequest, "remoteAddress",
2272                            groupTypeSettingsProperties.getProperty("remoteAddress"));
2273    
2274                    remoteAddress = stripProtocolFromRemoteAddress(remoteAddress);
2275    
2276                    int remotePort = ParamUtil.getInteger(
2277                            portletRequest, "remotePort",
2278                            GetterUtil.getInteger(
2279                                    groupTypeSettingsProperties.getProperty("remotePort")));
2280                    String remotePathContext = ParamUtil.getString(
2281                            portletRequest, "remotePathContext",
2282                            groupTypeSettingsProperties.getProperty("remotePathContext"));
2283                    boolean secureConnection = ParamUtil.getBoolean(
2284                            portletRequest, "secureConnection",
2285                            GetterUtil.getBoolean(
2286                                    groupTypeSettingsProperties.getProperty("secureConnection")));
2287                    long remoteGroupId = ParamUtil.getLong(
2288                            portletRequest, "remoteGroupId",
2289                            GetterUtil.getLong(
2290                                    groupTypeSettingsProperties.getProperty("remoteGroupId")));
2291                    boolean remotePrivateLayout = ParamUtil.getBoolean(
2292                            portletRequest, "remotePrivateLayout");
2293    
2294                    validateRemote(
2295                            remoteAddress, remotePort, remotePathContext, secureConnection,
2296                            remoteGroupId);
2297    
2298                    DateRange dateRange = ExportImportHelperUtil.getDateRange(
2299                            portletRequest, groupId, privateLayout, 0, null,
2300                            "fromLastPublishDate");
2301    
2302                    if (schedule) {
2303                            String groupName = getSchedulerGroupName(
2304                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, groupId);
2305    
2306                            int recurrenceType = ParamUtil.getInteger(
2307                                    portletRequest, "recurrenceType");
2308    
2309                            Calendar startCalendar = ExportImportHelperUtil.getCalendar(
2310                                    portletRequest, "schedulerStartDate", true);
2311    
2312                            String cronText = SchedulerEngineHelperUtil.getCronText(
2313                                    portletRequest, startCalendar, true, recurrenceType);
2314    
2315                            Date schedulerEndDate = null;
2316    
2317                            int endDateType = ParamUtil.getInteger(
2318                                    portletRequest, "endDateType");
2319    
2320                            if (endDateType == 1) {
2321                                    Calendar endCalendar = ExportImportHelperUtil.getCalendar(
2322                                            portletRequest, "schedulerEndDate", true);
2323    
2324                                    schedulerEndDate = endCalendar.getTime();
2325                            }
2326    
2327                            String description = ParamUtil.getString(
2328                                    portletRequest, "description");
2329    
2330                            LayoutServiceUtil.schedulePublishToRemote(
2331                                    groupId, privateLayout, layoutIdMap, parameterMap,
2332                                    remoteAddress, remotePort, remotePathContext, secureConnection,
2333                                    remoteGroupId, remotePrivateLayout, dateRange.getStartDate(),
2334                                    dateRange.getEndDate(), groupName, cronText,
2335                                    startCalendar.getTime(), schedulerEndDate, description);
2336                    }
2337                    else {
2338                            MessageStatus messageStatus = new MessageStatus();
2339    
2340                            messageStatus.startTimer();
2341    
2342                            try {
2343                                    copyRemoteLayouts(
2344                                            groupId, privateLayout, layoutIdMap, parameterMap,
2345                                            remoteAddress, remotePort, remotePathContext,
2346                                            secureConnection, remoteGroupId, remotePrivateLayout,
2347                                            dateRange.getStartDate(), dateRange.getEndDate());
2348                            }
2349                            catch (Exception e) {
2350                                    messageStatus.setException(e);
2351    
2352                                    throw e;
2353                            }
2354                            finally {
2355                                    messageStatus.stopTimer();
2356    
2357                                    LayoutsRemotePublisherRequest publisherRequest =
2358                                            new LayoutsRemotePublisherRequest(
2359                                                    themeDisplay.getUserId(), groupId, privateLayout,
2360                                                    layoutIdMap, parameterMap, remoteAddress, remotePort,
2361                                                    remotePathContext, secureConnection, remoteGroupId,
2362                                                    remotePrivateLayout, dateRange.getStartDate(),
2363                                                    dateRange.getEndDate());
2364    
2365                                    messageStatus.setPayload(publisherRequest);
2366    
2367                                    MessageBusUtil.sendMessage(
2368                                            DestinationNames.MESSAGE_BUS_MESSAGE_STATUS, messageStatus);
2369                            }
2370                    }
2371            }
2372    
2373            protected void setRecentLayoutBranchId(
2374                    PortalPreferences portalPreferences, long layoutSetBranchId, long plid,
2375                    long layoutBranchId) {
2376    
2377                    portalPreferences.setValue(
2378                            Staging.class.getName(),
2379                            getRecentLayoutBranchIdKey(layoutSetBranchId, plid),
2380                            String.valueOf(layoutBranchId));
2381            }
2382    
2383            protected void setRecentLayoutRevisionId(
2384                            PortalPreferences portalPreferences, long layoutSetBranchId,
2385                            long plid, long layoutRevisionId)
2386                    throws SystemException {
2387    
2388                    long layoutBranchId = 0;
2389    
2390                    try {
2391                            LayoutRevision layoutRevision =
2392                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2393                                            layoutRevisionId);
2394    
2395                            layoutBranchId = layoutRevision.getLayoutBranchId();
2396    
2397                            LayoutRevision lastLayoutRevision =
2398                                    LayoutRevisionLocalServiceUtil.getLayoutRevision(
2399                                            layoutSetBranchId, layoutBranchId, plid);
2400    
2401                            if (lastLayoutRevision.getLayoutRevisionId() == layoutRevisionId) {
2402                                    deleteRecentLayoutRevisionId(
2403                                            portalPreferences, layoutSetBranchId, plid);
2404                            }
2405                            else {
2406                                    portalPreferences.setValue(
2407                                            Staging.class.getName(),
2408                                            getRecentLayoutRevisionIdKey(layoutSetBranchId, plid),
2409                                            String.valueOf(layoutRevisionId));
2410                            }
2411                    }
2412                    catch (PortalException pe) {
2413                            if (_log.isWarnEnabled()) {
2414                                    _log.warn("Unable to set recent layout revision ID", pe);
2415                            }
2416                    }
2417    
2418                    portalPreferences.setValue(
2419                            Staging.class.getName(),
2420                            getRecentLayoutBranchIdKey(layoutSetBranchId, plid),
2421                            String.valueOf(layoutBranchId));
2422            }
2423    
2424            protected String stripProtocolFromRemoteAddress(String remoteAddress) {
2425                    if (remoteAddress.startsWith(Http.HTTP_WITH_SLASH)) {
2426                            remoteAddress = remoteAddress.substring(
2427                                    Http.HTTP_WITH_SLASH.length());
2428                    }
2429                    else if (remoteAddress.startsWith(Http.HTTPS_WITH_SLASH)) {
2430                            remoteAddress = remoteAddress.substring(
2431                                    Http.HTTPS_WITH_SLASH.length());
2432                    }
2433    
2434                    return remoteAddress;
2435            }
2436    
2437            protected void updateGroupTypeSettingsProperties(
2438                            Group group, String remoteAddress, int remotePort,
2439                            String remotePathContext, boolean secureConnection,
2440                            long remoteGroupId)
2441                    throws Exception {
2442    
2443                    UnicodeProperties typeSettingsProperties =
2444                            group.getTypeSettingsProperties();
2445    
2446                    typeSettingsProperties.setProperty("remoteAddress", remoteAddress);
2447                    typeSettingsProperties.setProperty(
2448                            "remoteGroupId", String.valueOf(remoteGroupId));
2449                    typeSettingsProperties.setProperty(
2450                            "remotePathContext", remotePathContext);
2451                    typeSettingsProperties.setProperty(
2452                            "remotePort", String.valueOf(remotePort));
2453                    typeSettingsProperties.setProperty(
2454                            "secureConnection", String.valueOf(secureConnection));
2455    
2456                    group.setTypeSettingsProperties(typeSettingsProperties);
2457    
2458                    GroupLocalServiceUtil.updateGroup(group);
2459            }
2460    
2461            private static Log _log = LogFactoryUtil.getLog(StagingImpl.class);
2462    
2463    }