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