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.portlet.sites.util;
016    
017    import com.liferay.portal.RequiredLayoutException;
018    import com.liferay.portal.events.EventsProcessorUtil;
019    import com.liferay.portal.kernel.dao.orm.QueryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024    import com.liferay.portal.kernel.lar.UserIdStrategy;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.ArrayUtil;
028    import com.liferay.portal.kernel.util.FileUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.OrderByComparator;
031    import com.liferay.portal.kernel.util.ParamUtil;
032    import com.liferay.portal.kernel.util.PrefsPropsUtil;
033    import com.liferay.portal.kernel.util.PropsKeys;
034    import com.liferay.portal.kernel.util.StringBundler;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.StringUtil;
037    import com.liferay.portal.kernel.util.SystemProperties;
038    import com.liferay.portal.kernel.util.UnicodeProperties;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
041    import com.liferay.portal.model.Group;
042    import com.liferay.portal.model.GroupConstants;
043    import com.liferay.portal.model.Layout;
044    import com.liferay.portal.model.LayoutConstants;
045    import com.liferay.portal.model.LayoutPrototype;
046    import com.liferay.portal.model.LayoutSet;
047    import com.liferay.portal.model.LayoutSetPrototype;
048    import com.liferay.portal.model.LayoutTypePortlet;
049    import com.liferay.portal.model.Lock;
050    import com.liferay.portal.model.Organization;
051    import com.liferay.portal.model.OrganizationConstants;
052    import com.liferay.portal.model.PortletConstants;
053    import com.liferay.portal.model.ResourceConstants;
054    import com.liferay.portal.model.Role;
055    import com.liferay.portal.model.RoleConstants;
056    import com.liferay.portal.model.User;
057    import com.liferay.portal.model.UserGroup;
058    import com.liferay.portal.model.impl.VirtualLayout;
059    import com.liferay.portal.security.auth.PrincipalException;
060    import com.liferay.portal.security.permission.ActionKeys;
061    import com.liferay.portal.security.permission.PermissionChecker;
062    import com.liferay.portal.security.permission.PermissionThreadLocal;
063    import com.liferay.portal.security.permission.ResourceActionsUtil;
064    import com.liferay.portal.service.GroupLocalServiceUtil;
065    import com.liferay.portal.service.GroupServiceUtil;
066    import com.liferay.portal.service.LayoutLocalServiceUtil;
067    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
068    import com.liferay.portal.service.LayoutServiceUtil;
069    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
070    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
071    import com.liferay.portal.service.LayoutSetServiceUtil;
072    import com.liferay.portal.service.LockLocalServiceUtil;
073    import com.liferay.portal.service.OrganizationLocalServiceUtil;
074    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
075    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
076    import com.liferay.portal.service.RoleLocalServiceUtil;
077    import com.liferay.portal.service.ServiceContext;
078    import com.liferay.portal.service.ServiceContextFactory;
079    import com.liferay.portal.service.ServiceContextThreadLocal;
080    import com.liferay.portal.service.UserGroupLocalServiceUtil;
081    import com.liferay.portal.service.UserLocalServiceUtil;
082    import com.liferay.portal.service.impl.LayoutLocalServiceVirtualLayoutsAdvice;
083    import com.liferay.portal.service.permission.GroupPermissionUtil;
084    import com.liferay.portal.service.permission.LayoutPermissionUtil;
085    import com.liferay.portal.service.permission.PortalPermissionUtil;
086    import com.liferay.portal.service.permission.PortletPermissionUtil;
087    import com.liferay.portal.service.persistence.LayoutSetUtil;
088    import com.liferay.portal.service.persistence.LayoutUtil;
089    import com.liferay.portal.theme.PortletDisplay;
090    import com.liferay.portal.theme.ThemeDisplay;
091    import com.liferay.portal.util.LayoutSettings;
092    import com.liferay.portal.util.PortalUtil;
093    import com.liferay.portal.util.PortletKeys;
094    import com.liferay.portal.util.PropsValues;
095    import com.liferay.portal.util.WebKeys;
096    import com.liferay.portlet.PortletPreferencesFactoryUtil;
097    import com.liferay.portlet.PortletPreferencesImpl;
098    
099    import java.io.File;
100    import java.io.InputStream;
101    
102    import java.util.ArrayList;
103    import java.util.Collections;
104    import java.util.Date;
105    import java.util.LinkedHashMap;
106    import java.util.List;
107    import java.util.Locale;
108    import java.util.Map;
109    
110    import javax.portlet.ActionRequest;
111    import javax.portlet.ActionResponse;
112    import javax.portlet.PortletPreferences;
113    import javax.portlet.PortletURL;
114    import javax.portlet.RenderRequest;
115    import javax.portlet.RenderResponse;
116    
117    import javax.servlet.http.HttpServletRequest;
118    import javax.servlet.http.HttpServletResponse;
119    
120    /**
121     * @author Raymond Aug??
122     * @author Ryan Park
123     * @author Zsolt Berentey
124     */
125    public class SitesImpl implements Sites {
126    
127            @Override
128            public void addMergeFailFriendlyURLLayout(Layout layout)
129                    throws PortalException, SystemException {
130    
131                    LayoutSet layoutSet = layout.getLayoutSet();
132    
133                    layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
134                            layoutSet.getGroupId(), layoutSet.isPrivateLayout());
135    
136                    UnicodeProperties settingsProperties =
137                            layoutSet.getSettingsProperties();
138    
139                    String mergeFailFriendlyURLLayouts =
140                            settingsProperties.getProperty(
141                                    MERGE_FAIL_FRIENDLY_URL_LAYOUTS, StringPool.BLANK);
142    
143                    mergeFailFriendlyURLLayouts = StringUtil.add(
144                            mergeFailFriendlyURLLayouts, layout.getUuid());
145    
146                    settingsProperties.setProperty(
147                            MERGE_FAIL_FRIENDLY_URL_LAYOUTS, mergeFailFriendlyURLLayouts);
148    
149                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
150            }
151    
152            @Override
153            public void addPortletBreadcrumbEntries(
154                            Group group, HttpServletRequest request,
155                            RenderResponse renderResponse)
156                    throws Exception {
157    
158                    PortletURL portletURL = renderResponse.createRenderURL();
159    
160                    portletURL.setParameter("struts_action", "/sites_admin/view");
161    
162                    List<Group> ancestorGroups = group.getAncestors();
163    
164                    Collections.reverse(ancestorGroups);
165    
166                    for (Group ancestorGroup : ancestorGroups) {
167                            portletURL.setParameter(
168                                    "groupId", String.valueOf(ancestorGroup.getGroupId()));
169    
170                            PortalUtil.addPortletBreadcrumbEntry(
171                                    request, ancestorGroup.getDescriptiveName(),
172                                    portletURL.toString());
173                    }
174    
175                    Group unescapedGroup = group.toUnescapedModel();
176    
177                    portletURL.setParameter(
178                            "groupId", String.valueOf(unescapedGroup.getGroupId()));
179    
180                    PortalUtil.addPortletBreadcrumbEntry(
181                            request, unescapedGroup.getDescriptiveName(),
182                            portletURL.toString());
183            }
184    
185            @Override
186            public void addPortletBreadcrumbEntries(
187                            Group group, String pagesName, PortletURL redirectURL,
188                            HttpServletRequest request, RenderResponse renderResponse)
189                    throws Exception {
190    
191                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
192                            com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
193    
194                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
195    
196                    String portletName = portletDisplay.getPortletName();
197    
198                    if ((renderResponse == null) ||
199                            portletName.equals(PortletKeys.GROUP_PAGES) ||
200                            portletName.equals(PortletKeys.MY_PAGES)) {
201    
202                            return;
203                    }
204    
205                    Group unescapedGroup = group.toUnescapedModel();
206    
207                    Locale locale = themeDisplay.getLocale();
208    
209                    if (group.isLayoutPrototype()) {
210                            PortalUtil.addPortletBreadcrumbEntry(
211                                    request, LanguageUtil.get(locale, "page-template"), null);
212    
213                            PortalUtil.addPortletBreadcrumbEntry(
214                                    request, unescapedGroup.getDescriptiveName(),
215                                    redirectURL.toString());
216                    }
217                    else {
218                            PortalUtil.addPortletBreadcrumbEntry(
219                                    request, unescapedGroup.getDescriptiveName(), null);
220                    }
221    
222                    if (!group.isLayoutPrototype()) {
223                            PortalUtil.addPortletBreadcrumbEntry(
224                                    request, LanguageUtil.get(locale, pagesName),
225                                    redirectURL.toString());
226                    }
227            }
228    
229            @Override
230            public void applyLayoutPrototype(
231                            LayoutPrototype layoutPrototype, Layout targetLayout,
232                            boolean linkEnabled)
233                    throws Exception {
234    
235                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
236    
237                    ServiceContext serviceContext =
238                            ServiceContextThreadLocal.getServiceContext();
239    
240                    serviceContext.setAttribute("layoutPrototypeLinkEnabled", linkEnabled);
241                    serviceContext.setAttribute(
242                            "layoutPrototypeUuid", layoutPrototype.getUuid());
243    
244                    targetLayout = LayoutLocalServiceUtil.updateLayout(
245                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
246                            targetLayout.getLayoutId(), targetLayout.getParentLayoutId(),
247                            targetLayout.getNameMap(), targetLayout.getTitleMap(),
248                            targetLayout.getDescriptionMap(), targetLayout.getKeywordsMap(),
249                            targetLayout.getRobotsMap(), layoutPrototypeLayout.getType(),
250                            targetLayout.getHidden(), targetLayout.getFriendlyURLMap(),
251                            targetLayout.getIconImage(), null, serviceContext);
252    
253                    targetLayout = LayoutLocalServiceUtil.updateLayout(
254                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
255                            targetLayout.getLayoutId(),
256                            layoutPrototypeLayout.getTypeSettings());
257    
258                    copyPortletPermissions(targetLayout, layoutPrototypeLayout);
259    
260                    copyPortletSetups(layoutPrototypeLayout, targetLayout);
261    
262                    copyLookAndFeel(targetLayout, layoutPrototypeLayout);
263    
264                    targetLayout = LayoutLocalServiceUtil.getLayout(targetLayout.getPlid());
265    
266                    UnicodeProperties typeSettingsProperties =
267                            targetLayout.getTypeSettingsProperties();
268    
269                    typeSettingsProperties.setProperty(
270                            LAST_MERGE_TIME,
271                            String.valueOf(targetLayout.getModifiedDate().getTime()));
272    
273                    LayoutLocalServiceUtil.updateLayout(targetLayout);
274    
275                    UnicodeProperties prototypeTypeSettingsProperties =
276                            layoutPrototypeLayout.getTypeSettingsProperties();
277    
278                    prototypeTypeSettingsProperties.setProperty(MERGE_FAIL_COUNT, "0");
279    
280                    LayoutLocalServiceUtil.updateLayout(layoutPrototypeLayout);
281            }
282    
283            @Override
284            public void copyLayout(
285                            long userId, Layout sourceLayout, Layout targetLayout,
286                            ServiceContext serviceContext)
287                    throws Exception {
288    
289                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
290                            serviceContext);
291    
292                    parameterMap.put(
293                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
294                            new String[] {Boolean.FALSE.toString()});
295    
296                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
297                            sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
298                            new long[] {sourceLayout.getLayoutId()}, parameterMap, null, null);
299    
300                    try {
301                            LayoutLocalServiceUtil.importLayouts(
302                                    userId, targetLayout.getGroupId(),
303                                    targetLayout.isPrivateLayout(), parameterMap, file);
304                    }
305                    finally {
306                            file.delete();
307                    }
308            }
309    
310            @Override
311            public void copyLookAndFeel(Layout targetLayout, Layout sourceLayout)
312                    throws Exception {
313    
314                    LayoutLocalServiceUtil.updateLookAndFeel(
315                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
316                            targetLayout.getLayoutId(), sourceLayout.getThemeId(),
317                            sourceLayout.getColorSchemeId(), sourceLayout.getCss(), false);
318    
319                    LayoutLocalServiceUtil.updateLookAndFeel(
320                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
321                            targetLayout.getLayoutId(), sourceLayout.getWapThemeId(),
322                            sourceLayout.getWapColorSchemeId(), sourceLayout.getCss(), true);
323            }
324    
325            @Override
326            public void copyPortletPermissions(Layout targetLayout, Layout sourceLayout)
327                    throws Exception {
328    
329                    long companyId = targetLayout.getCompanyId();
330    
331                    List<Role> roles = RoleLocalServiceUtil.getRoles(companyId);
332    
333                    LayoutTypePortlet sourceLayoutTypePortlet =
334                            (LayoutTypePortlet)sourceLayout.getLayoutType();
335    
336                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
337    
338                    for (String sourcePortletId : sourcePortletIds) {
339                            String resourceName = PortletConstants.getRootPortletId(
340                                    sourcePortletId);
341    
342                            String sourceResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
343                                    sourceLayout.getPlid(), sourcePortletId);
344    
345                            String targetResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
346                                    targetLayout.getPlid(), sourcePortletId);
347    
348                            List<String> actionIds =
349                                    ResourceActionsUtil.getPortletResourceActions(resourceName);
350    
351                            for (Role role : roles) {
352                                    String roleName = role.getName();
353    
354                                    if (roleName.equals(RoleConstants.ADMINISTRATOR) ||
355                                            (targetLayout.isPrivateLayout() &&
356                                             roleName.equals(RoleConstants.GUEST))) {
357    
358                                            continue;
359                                    }
360    
361                                    List<String> actions =
362                                            ResourcePermissionLocalServiceUtil.
363                                                    getAvailableResourcePermissionActionIds(
364                                                            companyId, resourceName,
365                                                            ResourceConstants.SCOPE_INDIVIDUAL,
366                                                            sourceResourcePrimKey, role.getRoleId(), actionIds);
367    
368                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
369                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
370                                            targetResourcePrimKey, role.getRoleId(),
371                                            actions.toArray(new String[actions.size()]));
372                            }
373                    }
374            }
375    
376            @Override
377            public void copyPortletSetups(Layout sourceLayout, Layout targetLayout)
378                    throws Exception {
379    
380                    LayoutTypePortlet sourceLayoutTypePortlet =
381                            (LayoutTypePortlet)sourceLayout.getLayoutType();
382    
383                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
384    
385                    for (String sourcePortletId : sourcePortletIds) {
386                            PortletPreferences sourcePreferences =
387                                    PortletPreferencesFactoryUtil.getPortletSetup(
388                                            sourceLayout, sourcePortletId, null);
389    
390                            PortletPreferencesImpl sourcePreferencesImpl =
391                                    (PortletPreferencesImpl)sourcePreferences;
392    
393                            PortletPreferences targetPreferences =
394                                    PortletPreferencesFactoryUtil.getPortletSetup(
395                                            targetLayout, sourcePortletId, null);
396    
397                            PortletPreferencesImpl targetPreferencesImpl =
398                                    (PortletPreferencesImpl)targetPreferences;
399    
400                            PortletPreferencesLocalServiceUtil.updatePreferences(
401                                    targetPreferencesImpl.getOwnerId(),
402                                    targetPreferencesImpl.getOwnerType(),
403                                    targetPreferencesImpl.getPlid(), sourcePortletId,
404                                    sourcePreferences);
405    
406                            if ((sourcePreferencesImpl.getOwnerId() !=
407                                            PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
408                                    (sourcePreferencesImpl.getOwnerType() !=
409                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) {
410    
411                                    sourcePreferences =
412                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
413                                                    sourceLayout, sourcePortletId);
414    
415                                    sourcePreferencesImpl =
416                                            (PortletPreferencesImpl)sourcePreferences;
417    
418                                    targetPreferences =
419                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
420                                                    targetLayout, sourcePortletId);
421    
422                                    targetPreferencesImpl =
423                                            (PortletPreferencesImpl)targetPreferences;
424    
425                                    PortletPreferencesLocalServiceUtil.updatePreferences(
426                                            targetPreferencesImpl.getOwnerId(),
427                                            targetPreferencesImpl.getOwnerType(),
428                                            targetPreferencesImpl.getPlid(), sourcePortletId,
429                                            sourcePreferences);
430                            }
431    
432                            ServiceContext serviceContext =
433                                    ServiceContextThreadLocal.getServiceContext();
434    
435                            updateLayoutScopes(
436                                    serviceContext.getUserId(), sourceLayout, targetLayout,
437                                    sourcePreferences, targetPreferences, sourcePortletId,
438                                    serviceContext.getLanguageId());
439                    }
440            }
441    
442            @Override
443            public void copyTypeSettings(Group sourceGroup, Group targetGroup)
444                    throws Exception {
445    
446                    GroupServiceUtil.updateGroup(
447                            targetGroup.getGroupId(), sourceGroup.getTypeSettings());
448            }
449    
450            @Override
451            public Object[] deleteLayout(
452                            ActionRequest actionRequest, ActionResponse actionResponse)
453                    throws Exception {
454    
455                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
456                            actionRequest);
457                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
458                            actionResponse);
459    
460                    return deleteLayout(request, response);
461            }
462    
463            @Override
464            public Object[] deleteLayout(
465                            HttpServletRequest request, HttpServletResponse response)
466                    throws Exception {
467    
468                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
469                            WebKeys.THEME_DISPLAY);
470    
471                    PermissionChecker permissionChecker =
472                            themeDisplay.getPermissionChecker();
473    
474                    long plid = ParamUtil.getLong(request, "plid");
475    
476                    long groupId = ParamUtil.getLong(request, "groupId");
477                    boolean privateLayout = ParamUtil.getBoolean(request, "privateLayout");
478                    long layoutId = ParamUtil.getLong(request, "layoutId");
479    
480                    Layout layout = null;
481    
482                    if (plid <= 0) {
483                            layout = LayoutLocalServiceUtil.getLayout(
484                                    groupId, privateLayout, layoutId);
485                    }
486                    else {
487                            layout = LayoutLocalServiceUtil.getLayout(plid);
488    
489                            groupId = layout.getGroupId();
490                            privateLayout = layout.isPrivateLayout();
491                            layoutId = layout.getLayoutId();
492                    }
493    
494                    Group group = layout.getGroup();
495                    String oldFriendlyURL = layout.getFriendlyURL(themeDisplay.getLocale());
496    
497                    if (group.isStagingGroup() &&
498                            !GroupPermissionUtil.contains(
499                                    permissionChecker, groupId, ActionKeys.MANAGE_STAGING) &&
500                            !GroupPermissionUtil.contains(
501                                    permissionChecker, groupId, ActionKeys.PUBLISH_STAGING)) {
502    
503                            throw new PrincipalException();
504                    }
505    
506                    if (LayoutPermissionUtil.contains(
507                                    permissionChecker, layout, ActionKeys.DELETE)) {
508    
509                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
510    
511                            EventsProcessorUtil.process(
512                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_DELETE,
513                                    layoutSettings.getConfigurationActionDelete(), request,
514                                    response);
515                    }
516    
517                    LayoutSet layoutSet = layout.getLayoutSet();
518    
519                    if (group.isGuest() && (layoutSet.getPageCount() == 1)) {
520                            throw new RequiredLayoutException(
521                                    RequiredLayoutException.AT_LEAST_ONE);
522                    }
523    
524                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
525                            request);
526    
527                    LayoutServiceUtil.deleteLayout(
528                            groupId, privateLayout, layoutId, serviceContext);
529    
530                    long newPlid = layout.getParentPlid();
531    
532                    if (newPlid <= 0) {
533                            Layout firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
534                                    layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
535                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
536    
537                            if (firstLayout != null) {
538                                    newPlid = firstLayout.getPlid();
539                            }
540                    }
541    
542                    return new Object[] {group, oldFriendlyURL, newPlid};
543            }
544    
545            @Override
546            public void deleteLayout(
547                            RenderRequest renderRequest, RenderResponse renderResponse)
548                    throws Exception {
549    
550                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
551                            renderRequest);
552                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
553                            renderResponse);
554    
555                    deleteLayout(request, response);
556            }
557    
558            @Override
559            public File exportLayoutSetPrototype(
560                            LayoutSetPrototype layoutSetPrototype,
561                            ServiceContext serviceContext)
562                    throws PortalException, SystemException {
563    
564                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
565    
566                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
567                            serviceContext);
568    
569                    return LayoutLocalServiceUtil.exportLayoutsAsFile(
570                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), null,
571                            parameterMap, null, null);
572            }
573    
574            @Override
575            public Long[] filterGroups(List<Group> groups, String[] names) {
576                    List<Long> groupIds = new ArrayList<Long>();
577    
578                    for (Group group : groups) {
579                            if (!ArrayUtil.contains(names, group.getName())) {
580                                    groupIds.add(group.getGroupId());
581                            }
582                    }
583    
584                    return ArrayUtil.toArray(ArrayUtil.toLongArray(groupIds));
585            }
586    
587            @Override
588            public Layout getLayoutSetPrototypeLayout(Layout layout) {
589                    try {
590                            LayoutSet layoutSet = layout.getLayoutSet();
591    
592                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
593                                    return null;
594                            }
595    
596                            LayoutSetPrototype layoutSetPrototype =
597                                    LayoutSetPrototypeLocalServiceUtil.
598                                            getLayoutSetPrototypeByUuidAndCompanyId(
599                                                    layoutSet.getLayoutSetPrototypeUuid(),
600                                                    layout.getCompanyId());
601    
602                            return LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
603                                    layout.getSourcePrototypeLayoutUuid(),
604                                    layoutSetPrototype.getGroupId(), true);
605                    }
606                    catch (Exception e) {
607                            _log.error(
608                                    "Unable to fetch the the layout set prototype's layout", e);
609                    }
610    
611                    return null;
612            }
613    
614            @Override
615            public Map<String, String[]> getLayoutSetPrototypeParameters(
616                    ServiceContext serviceContext) {
617    
618                    Map<String, String[]> parameterMap =
619                            new LinkedHashMap<String, String[]>();
620    
621                    parameterMap.put(
622                            PortletDataHandlerKeys.CATEGORIES,
623                            new String[] {Boolean.TRUE.toString()});
624                    parameterMap.put(
625                            PortletDataHandlerKeys.DATA_STRATEGY,
626                            new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
627                    parameterMap.put(
628                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
629                            new String[] {Boolean.TRUE.toString()});
630                    parameterMap.put(
631                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
632                            new String[] {Boolean.FALSE.toString()});
633                    parameterMap.put(
634                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
635                            new String[] {Boolean.TRUE.toString()});
636                    parameterMap.put(
637                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
638                            new String[] {Boolean.TRUE.toString()});
639                    parameterMap.put(
640                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
641                            new String[] {
642                                    PortletDataHandlerKeys.
643                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
644                            });
645                    parameterMap.put(
646                            PortletDataHandlerKeys.LOGO,
647                            new String[] {Boolean.TRUE.toString()});
648                    parameterMap.put(
649                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
650                            new String[] {Boolean.TRUE.toString()});
651                    parameterMap.put(
652                            PortletDataHandlerKeys.PERMISSIONS,
653                            new String[] {Boolean.TRUE.toString()});
654                    parameterMap.put(
655                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
656                            new String[] {Boolean.TRUE.toString()});
657                    parameterMap.put(
658                            PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL,
659                            new String[] {Boolean.TRUE.toString()});
660                    parameterMap.put(
661                            PortletDataHandlerKeys.PORTLET_DATA,
662                            new String[] {Boolean.TRUE.toString()});
663                    parameterMap.put(
664                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
665                            new String[] {Boolean.TRUE.toString()});
666                    parameterMap.put(
667                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
668                            new String[] {Boolean.TRUE.toString()});
669                    parameterMap.put(
670                            PortletDataHandlerKeys.THEME,
671                            new String[] {Boolean.FALSE.toString()});
672                    parameterMap.put(
673                            PortletDataHandlerKeys.THEME_REFERENCE,
674                            new String[] {Boolean.TRUE.toString()});
675                    parameterMap.put(
676                            PortletDataHandlerKeys.USER_ID_STRATEGY,
677                            new String[] {UserIdStrategy.CURRENT_USER_ID});
678    
679                    return parameterMap;
680            }
681    
682            /**
683             * Returns the number of failed merge attempts for the layout prototype
684             * since its last reset or update.
685             *
686             * @param  layoutPrototype the page template being checked for failed merge
687             *         attempts
688             * @return the number of failed merge attempts for the layout prototype
689             * @throws PortalException if no page was associated with the layout
690             *         prototype or if a portal exception occurred
691             * @throws SystemException if a system exception occurred
692             */
693            @Override
694            public int getMergeFailCount(LayoutPrototype layoutPrototype)
695                    throws PortalException, SystemException {
696    
697                    if ((layoutPrototype == null) ||
698                            (layoutPrototype.getLayoutPrototypeId() == 0)) {
699    
700                            return 0;
701                    }
702    
703                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
704    
705                    UnicodeProperties prototypeTypeSettingsProperties =
706                            layoutPrototypeLayout.getTypeSettingsProperties();
707    
708                    return GetterUtil.getInteger(
709                            prototypeTypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
710            }
711    
712            /**
713             * Returns the number of failed merge attempts for the layout set prototype
714             * since its last reset or update.
715             *
716             * @param  layoutSetPrototype the site template being checked for failed
717             *         merge attempts
718             * @return the number of failed merge attempts for the layout set prototype
719             * @throws PortalException if no site was associated with the layout set
720             *         prototype or if a portal exception occurred
721             * @throws SystemException if a system exception occurred
722             */
723            @Override
724            public int getMergeFailCount(LayoutSetPrototype layoutSetPrototype)
725                    throws PortalException, SystemException {
726    
727                    if ((layoutSetPrototype == null) ||
728                            (layoutSetPrototype.getLayoutSetPrototypeId() == 0)) {
729    
730                            return 0;
731                    }
732    
733                    LayoutSet layoutSetPrototypeLayoutSet =
734                            layoutSetPrototype.getLayoutSet();
735    
736                    UnicodeProperties layoutSetPrototypeSettingsProperties =
737                            layoutSetPrototypeLayoutSet.getSettingsProperties();
738    
739                    return GetterUtil.getInteger(
740                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
741            }
742    
743            @Override
744            public List<Layout> getMergeFailFriendlyURLLayouts(LayoutSet layoutSet)
745                    throws PortalException, SystemException {
746    
747                    if (layoutSet == null) {
748                            return Collections.emptyList();
749                    }
750    
751                    UnicodeProperties settingsProperties =
752                            layoutSet.getSettingsProperties();
753    
754                    String uuids = settingsProperties.getProperty(
755                            MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
756    
757                    if (Validator.isNotNull(uuids)) {
758                            List<Layout> layouts = new ArrayList<Layout>();
759    
760                            for (String uuid : StringUtil.split(uuids)) {
761                                    Layout layout =
762                                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
763                                                    uuid, layoutSet.getGroupId(),
764                                                    layoutSet.isPrivateLayout());
765    
766                                    layouts.add(layout);
767                            }
768    
769                            return layouts;
770                    }
771    
772                    return Collections.emptyList();
773            }
774    
775            @Override
776            public void importLayoutSetPrototype(
777                            LayoutSetPrototype layoutSetPrototype, InputStream inputStream,
778                            ServiceContext serviceContext)
779                    throws PortalException, SystemException {
780    
781                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
782    
783                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
784                            serviceContext);
785    
786                    setLayoutSetPrototypeLinkEnabledParameter(
787                            parameterMap, layoutSet, serviceContext);
788    
789                    LayoutServiceUtil.importLayouts(
790                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), parameterMap,
791                            inputStream);
792            }
793    
794            @Override
795            public boolean isContentSharingWithChildrenEnabled(Group group)
796                    throws SystemException {
797    
798                    UnicodeProperties typeSettingsProperties =
799                            group.getParentLiveGroupTypeSettingsProperties();
800    
801                    int companyContentSharingEnabled = PrefsPropsUtil.getInteger(
802                            group.getCompanyId(),
803                            PropsKeys.SITES_CONTENT_SHARING_WITH_CHILDREN_ENABLED);
804    
805                    if (companyContentSharingEnabled ==
806                                    CONTENT_SHARING_WITH_CHILDREN_DISABLED) {
807    
808                            return false;
809                    }
810    
811                    int groupContentSharingEnabled = GetterUtil.getInteger(
812                            typeSettingsProperties.getProperty(
813                                    "contentSharingWithChildrenEnabled"),
814                                    CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE);
815    
816                    if ((groupContentSharingEnabled ==
817                                    CONTENT_SHARING_WITH_CHILDREN_ENABLED) ||
818                            ((companyContentSharingEnabled ==
819                                    CONTENT_SHARING_WITH_CHILDREN_ENABLED_BY_DEFAULT) &&
820                             (groupContentSharingEnabled ==
821                                    CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE))) {
822    
823                            return true;
824                    }
825    
826                    return false;
827            }
828    
829            @Override
830            public boolean isLayoutDeleteable(Layout layout) {
831                    try {
832                            if (layout instanceof VirtualLayout) {
833                                    return false;
834                            }
835    
836                            if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
837                                    return true;
838                            }
839    
840                            LayoutSet layoutSet = layout.getLayoutSet();
841    
842                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
843                                    return true;
844                            }
845    
846                            if (LayoutLocalServiceUtil.hasLayoutSetPrototypeLayout(
847                                            layoutSet.getLayoutSetPrototypeUuid(),
848                                            layout.getCompanyId(),
849                                            layout.getSourcePrototypeLayoutUuid())) {
850    
851                                    return false;
852                            }
853                    }
854                    catch (Exception e) {
855                            if (_log.isDebugEnabled()) {
856                                    _log.debug(e, e);
857                            }
858                    }
859    
860                    return true;
861            }
862    
863            @Override
864            public boolean isLayoutModifiedSinceLastMerge(Layout layout) {
865                    if ((layout == null) ||
866                            Validator.isNull(layout.getSourcePrototypeLayoutUuid()) ||
867                            layout.isLayoutPrototypeLinkActive() ||
868                            !isLayoutUpdateable(layout)) {
869    
870                            return false;
871                    }
872    
873                    long lastMergeTime = GetterUtil.getLong(
874                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
875    
876                    Date existingLayoutModifiedDate = layout.getModifiedDate();
877    
878                    if ((existingLayoutModifiedDate != null) &&
879                            (existingLayoutModifiedDate.getTime() > lastMergeTime)) {
880    
881                            return true;
882                    }
883    
884                    return false;
885            }
886    
887            /**
888             * Returns <code>true</code> if the linked site template can be merged into
889             * the layout set. This method checks the current number of merge fail
890             * attempts stored for the linked site template and, if greater than the
891             * merge fail threshold, will return <code>false</code>.
892             *
893             * @param  group the site template's group, which is about to be merged into
894             *         the layout set
895             * @param  layoutSet the site in which the site template is attempting to
896             *         merge into
897             * @return <code>true</code> if the linked site template can be merged into
898             *         the layout set; <code>false</code> otherwise
899             * @throws PortalException if no site template was associated with the
900             *         layout set or if a portal exception occurred
901             * @throws SystemException if a system exception occurred
902             */
903            @Override
904            public boolean isLayoutSetMergeable(Group group, LayoutSet layoutSet)
905                    throws PortalException, SystemException {
906    
907                    if (!layoutSet.isLayoutSetPrototypeLinkActive() ||
908                            group.isLayoutPrototype() || group.isLayoutSetPrototype()) {
909    
910                            return false;
911                    }
912    
913                    UnicodeProperties settingsProperties =
914                            layoutSet.getSettingsProperties();
915    
916                    long lastMergeTime = GetterUtil.getLong(
917                            settingsProperties.getProperty(LAST_MERGE_TIME));
918    
919                    LayoutSetPrototype layoutSetPrototype =
920                            LayoutSetPrototypeLocalServiceUtil.
921                                    getLayoutSetPrototypeByUuidAndCompanyId(
922                                            layoutSet.getLayoutSetPrototypeUuid(),
923                                            layoutSet.getCompanyId());
924    
925                    Date modifiedDate = layoutSetPrototype.getModifiedDate();
926    
927                    if (lastMergeTime >= modifiedDate.getTime()) {
928                            return false;
929                    }
930    
931                    LayoutSet layoutSetPrototypeLayoutSet =
932                            layoutSetPrototype.getLayoutSet();
933    
934                    UnicodeProperties layoutSetPrototypeSettingsProperties =
935                            layoutSetPrototypeLayoutSet.getSettingsProperties();
936    
937                    int mergeFailCount = GetterUtil.getInteger(
938                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
939    
940                    if (mergeFailCount >
941                                    PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
942    
943                            if (_log.isWarnEnabled()) {
944                                    StringBundler sb = new StringBundler(6);
945    
946                                    sb.append("Merge not performed because the fail threshold ");
947                                    sb.append("was reached for layoutSetPrototypeId ");
948                                    sb.append(layoutSetPrototype.getLayoutSetPrototypeId());
949                                    sb.append(" and layoutId ");
950                                    sb.append(layoutSetPrototypeLayoutSet.getLayoutSetId());
951                                    sb.append(". Update the count in the database to try again.");
952    
953                                    _log.warn(sb.toString());
954                            }
955    
956                            return false;
957                    }
958    
959                    return true;
960            }
961    
962            @Override
963            public boolean isLayoutSetPrototypeUpdateable(LayoutSet layoutSet) {
964                    if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
965                            return true;
966                    }
967    
968                    try {
969                            LayoutSetPrototype layoutSetPrototype =
970                                    LayoutSetPrototypeLocalServiceUtil.
971                                            getLayoutSetPrototypeByUuidAndCompanyId(
972                                                    layoutSet.getLayoutSetPrototypeUuid(),
973                                                    layoutSet.getCompanyId());
974    
975                            String layoutsUpdateable = layoutSetPrototype.getSettingsProperty(
976                                    "layoutsUpdateable");
977    
978                            if (Validator.isNotNull(layoutsUpdateable)) {
979                                    return GetterUtil.getBoolean(layoutsUpdateable, true);
980                            }
981                    }
982                    catch (Exception e) {
983                            if (_log.isDebugEnabled()) {
984                                    _log.debug(e, e);
985                            }
986                    }
987    
988                    return true;
989            }
990    
991            @Override
992            public boolean isLayoutSortable(Layout layout) {
993                    return isLayoutDeleteable(layout);
994            }
995    
996            @Override
997            public boolean isLayoutUpdateable(Layout layout) {
998                    try {
999                            if (layout instanceof VirtualLayout) {
1000                                    return false;
1001                            }
1002    
1003                            if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
1004                                    Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
1005    
1006                                    return true;
1007                            }
1008    
1009                            LayoutSet layoutSet = layout.getLayoutSet();
1010    
1011                            if (layoutSet.isLayoutSetPrototypeLinkActive()) {
1012                                    boolean layoutSetPrototypeUpdateable =
1013                                            isLayoutSetPrototypeUpdateable(layoutSet);
1014    
1015                                    if (!layoutSetPrototypeUpdateable) {
1016                                            return false;
1017                                    }
1018    
1019                                    Layout layoutSetPrototypeLayout = getLayoutSetPrototypeLayout(
1020                                            layout);
1021    
1022                                    String layoutUpdateable =
1023                                            layoutSetPrototypeLayout.getTypeSettingsProperty(
1024                                                    LAYOUT_UPDATEABLE);
1025    
1026                                    if (Validator.isNull(layoutUpdateable)) {
1027                                            return true;
1028                                    }
1029    
1030                                    return GetterUtil.getBoolean(layoutUpdateable);
1031                            }
1032                    }
1033                    catch (Exception e) {
1034                            if (_log.isDebugEnabled()) {
1035                                    _log.debug(e, e);
1036                            }
1037                    }
1038    
1039                    return true;
1040            }
1041    
1042            @Override
1043            public boolean isOrganizationUser(
1044                            long companyId, Group group, User user,
1045                            List<String> organizationNames)
1046                    throws Exception {
1047    
1048                    boolean organizationUser = false;
1049    
1050                    LinkedHashMap<String, Object> organizationParams =
1051                            new LinkedHashMap<String, Object>();
1052    
1053                    organizationParams.put(
1054                            "groupOrganization", new Long(group.getGroupId()));
1055                    organizationParams.put(
1056                            "organizationsGroups", new Long(group.getGroupId()));
1057    
1058                    List<Organization> organizationsGroups =
1059                            OrganizationLocalServiceUtil.search(
1060                                    companyId, OrganizationConstants.ANY_PARENT_ORGANIZATION_ID,
1061                                    null, null, null, null, organizationParams, QueryUtil.ALL_POS,
1062                                    QueryUtil.ALL_POS);
1063    
1064                    for (Organization organization : organizationsGroups) {
1065                            for (long userOrganizationId : user.getOrganizationIds()) {
1066                                    if (userOrganizationId == organization.getOrganizationId()) {
1067                                            organizationNames.add(organization.getName());
1068    
1069                                            organizationUser = true;
1070                                    }
1071                            }
1072                    }
1073    
1074                    return organizationUser;
1075            }
1076    
1077            @Override
1078            public boolean isUserGroupLayoutSetViewable(
1079                            PermissionChecker permissionChecker, Group userGroupGroup)
1080                    throws PortalException, SystemException {
1081    
1082                    if (!userGroupGroup.isUserGroup()) {
1083                            return false;
1084                    }
1085    
1086                    if (GroupPermissionUtil.contains(
1087                                    permissionChecker, userGroupGroup.getGroupId(),
1088                                    ActionKeys.VIEW)) {
1089    
1090                            return true;
1091                    }
1092    
1093                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
1094                            userGroupGroup.getClassPK());
1095    
1096                    if (UserLocalServiceUtil.hasUserGroupUser(
1097                                    userGroup.getUserGroupId(), permissionChecker.getUserId())) {
1098    
1099                            return true;
1100                    }
1101                    else {
1102                            return false;
1103                    }
1104            }
1105    
1106            @Override
1107            public boolean isUserGroupUser(
1108                            long companyId, Group group, User user, List<String> userGroupNames)
1109                    throws Exception {
1110    
1111                    boolean userGroupUser = false;
1112    
1113                    LinkedHashMap<String, Object> userGroupParams =
1114                            new LinkedHashMap<String, Object>();
1115    
1116                    userGroupParams.put("userGroupsGroups", new Long(group.getGroupId()));
1117    
1118                    List<UserGroup> userGroupsGroups = UserGroupLocalServiceUtil.search(
1119                            companyId, null, userGroupParams, QueryUtil.ALL_POS,
1120                            QueryUtil.ALL_POS, (OrderByComparator)null);
1121    
1122                    for (UserGroup userGroup : userGroupsGroups) {
1123                            for (long userGroupId : user.getUserGroupIds()) {
1124                                    if (userGroupId == userGroup.getUserGroupId()) {
1125                                            userGroupNames.add(userGroup.getName());
1126    
1127                                            userGroupUser = true;
1128                                    }
1129                            }
1130                    }
1131    
1132                    return userGroupUser;
1133            }
1134    
1135            @Override
1136            public void mergeLayoutPrototypeLayout(Group group, Layout layout)
1137                    throws Exception {
1138    
1139                    String sourcePrototypeLayoutUuid =
1140                            layout.getSourcePrototypeLayoutUuid();
1141    
1142                    if (Validator.isNull(sourcePrototypeLayoutUuid)) {
1143                            doMergeLayoutPrototypeLayout(group, layout);
1144    
1145                            return;
1146                    }
1147    
1148                    LayoutSet layoutSet = layout.getLayoutSet();
1149    
1150                    long layoutSetPrototypeId = layoutSet.getLayoutSetPrototypeId();
1151    
1152                    if (layoutSetPrototypeId > 0) {
1153                            Group layoutSetPrototypeGroup =
1154                                    GroupLocalServiceUtil.getLayoutSetPrototypeGroup(
1155                                            layout.getCompanyId(), layoutSetPrototypeId);
1156    
1157                            Layout sourcePrototypeLayout =
1158                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1159                                            sourcePrototypeLayoutUuid,
1160                                            layoutSetPrototypeGroup.getGroupId(), true);
1161    
1162                            doMergeLayoutPrototypeLayout(
1163                                    layoutSetPrototypeGroup, sourcePrototypeLayout);
1164                    }
1165    
1166                    doMergeLayoutPrototypeLayout(group, layout);
1167            }
1168    
1169            /**
1170             * @deprecated As of 6.2.0, replaced by {@link
1171             *             #mergeLayoutPrototypeLayout(Group, Layout)}
1172             */
1173            @Override
1174            public void mergeLayoutProtypeLayout(Group group, Layout layout)
1175                    throws Exception {
1176    
1177                    mergeLayoutPrototypeLayout(group, layout);
1178            }
1179    
1180            @Override
1181            public void mergeLayoutSetPrototypeLayouts(Group group, LayoutSet layoutSet)
1182                    throws Exception {
1183    
1184                    if (!isLayoutSetMergeable(group, layoutSet)) {
1185                            return;
1186                    }
1187    
1188                    UnicodeProperties settingsProperties =
1189                            layoutSet.getSettingsProperties();
1190    
1191                    long lastMergeTime = GetterUtil.getLong(
1192                            settingsProperties.getProperty(LAST_MERGE_TIME));
1193    
1194                    LayoutSetPrototype layoutSetPrototype =
1195                            LayoutSetPrototypeLocalServiceUtil.
1196                                    getLayoutSetPrototypeByUuidAndCompanyId(
1197                                            layoutSet.getLayoutSetPrototypeUuid(),
1198                                            layoutSet.getCompanyId());
1199    
1200                    LayoutSet layoutSetPrototypeLayoutSet =
1201                            layoutSetPrototype.getLayoutSet();
1202    
1203                    UnicodeProperties layoutSetPrototypeSettingsProperties =
1204                            layoutSetPrototypeLayoutSet.getSettingsProperties();
1205    
1206                    int mergeFailCount = GetterUtil.getInteger(
1207                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1208    
1209                    String owner = PortalUUIDUtil.generate();
1210    
1211                    try {
1212                            Lock lock = LockLocalServiceUtil.lock(
1213                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1214                                    String.valueOf(layoutSet.getLayoutSetId()), owner);
1215    
1216                            // Double deep check
1217    
1218                            if (!owner.equals(lock.getOwner())) {
1219                                    Date createDate = lock.getCreateDate();
1220    
1221                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1222                                                    PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1223    
1224                                            // Acquire lock if the lock is older than the lock max time
1225    
1226                                            lock = LockLocalServiceUtil.lock(
1227                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1228                                                    String.valueOf(layoutSet.getLayoutSetId()),
1229                                                    lock.getOwner(), owner);
1230    
1231                                            // Check if acquiring the lock succeeded or if another
1232                                            // process has the lock
1233    
1234                                            if (!owner.equals(lock.getOwner())) {
1235                                                    return;
1236                                            }
1237                                    }
1238                                    else {
1239                                            return;
1240                                    }
1241                            }
1242                    }
1243                    catch (Exception e) {
1244                            return;
1245                    }
1246    
1247                    try {
1248                            boolean importData = true;
1249    
1250                            long lastResetTime = GetterUtil.getLong(
1251                                    settingsProperties.getProperty(LAST_RESET_TIME));
1252    
1253                            if ((lastMergeTime > 0) || (lastResetTime > 0)) {
1254                                    importData = false;
1255                            }
1256    
1257                            Map<String, String[]> parameterMap =
1258                                    getLayoutSetPrototypesParameters(importData);
1259    
1260                            removeMergeFailFriendlyURLLayouts(layoutSet);
1261    
1262                            importLayoutSetPrototype(
1263                                    layoutSetPrototype, layoutSet.getGroupId(),
1264                                    layoutSet.isPrivateLayout(), parameterMap, importData);
1265                    }
1266                    catch (Exception e) {
1267                            _log.error(e, e);
1268    
1269                            layoutSetPrototypeSettingsProperties.setProperty(
1270                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1271    
1272                            // Invoke updateImpl so that we do not trigger the listeners
1273    
1274                            LayoutSetUtil.updateImpl(layoutSetPrototypeLayoutSet);
1275                    }
1276                    finally {
1277                            LockLocalServiceUtil.unlock(
1278                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1279                                    String.valueOf(layoutSet.getLayoutSetId()), owner);
1280                    }
1281            }
1282    
1283            /**
1284             * @deprecated As of 6.2.0, replaced by {@link
1285             *             #mergeLayoutSetPrototypeLayouts(Group, LayoutSet)}
1286             */
1287            @Override
1288            public void mergeLayoutSetProtypeLayouts(Group group, LayoutSet layoutSet)
1289                    throws Exception {
1290    
1291                    mergeLayoutSetPrototypeLayouts(group, layoutSet);
1292            }
1293    
1294            @Override
1295            public void removeMergeFailFriendlyURLLayouts(LayoutSet layoutSet)
1296                    throws SystemException {
1297    
1298                    UnicodeProperties settingsProperties =
1299                            layoutSet.getSettingsProperties();
1300    
1301                    settingsProperties.remove(MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
1302    
1303                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
1304            }
1305    
1306            /**
1307             * Checks the permissions necessary for resetting the layout. If sufficient,
1308             * the layout is reset by calling {@link #doResetPrototype(Layout)}.
1309             *
1310             * @param  layout the page being checked for sufficient permissions
1311             * @throws PortalException if no site was associated with the layout, if the
1312             *         user did not have permission to update the layout or the layout's
1313             *         site, or if a portal exception occurred
1314             * @throws SystemException if a system exception occurred
1315             */
1316            @Override
1317            public void resetPrototype(Layout layout)
1318                    throws PortalException, SystemException {
1319    
1320                    checkResetPrototypePermissions(layout.getGroup(), layout);
1321    
1322                    doResetPrototype(layout);
1323            }
1324    
1325            /**
1326             * Checks the permissions necessary for resetting the layout set. If
1327             * sufficient, the layout set is reset by calling {@link
1328             * #doResetPrototype(LayoutSet)}.
1329             *
1330             * @param  layoutSet the site being checked for sufficient permissions
1331             * @throws PortalException if the user did not have permission to update the
1332             *         site or if a portal exception occurred
1333             * @throws SystemException if a system exception occurred
1334             */
1335            @Override
1336            public void resetPrototype(LayoutSet layoutSet)
1337                    throws PortalException, SystemException {
1338    
1339                    checkResetPrototypePermissions(layoutSet.getGroup(), null);
1340    
1341                    doResetPrototype(layoutSet);
1342            }
1343    
1344            /**
1345             * Sets the number of failed merge attempts for the layout prototype to a
1346             * new value.
1347             *
1348             * @param  layoutPrototype the page template of the counter being updated
1349             * @param  newMergeFailCount the new value of the counter
1350             * @throws PortalException if no page was associated with the layout
1351             *         prototype, if the user did not have permission to update the
1352             *         page, or if a portal exception occurred
1353             * @throws SystemException if a system exception occurred
1354             */
1355            @Override
1356            public void setMergeFailCount(
1357                            LayoutPrototype layoutPrototype, int newMergeFailCount)
1358                    throws PortalException, SystemException {
1359    
1360                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
1361    
1362                    UnicodeProperties prototypeTypeSettingsProperties =
1363                            layoutPrototypeLayout.getTypeSettingsProperties();
1364    
1365                    if (newMergeFailCount == 0) {
1366                            prototypeTypeSettingsProperties.remove(MERGE_FAIL_COUNT);
1367                    }
1368                    else {
1369                            prototypeTypeSettingsProperties.setProperty(
1370                                    MERGE_FAIL_COUNT, String.valueOf(newMergeFailCount));
1371                    }
1372    
1373                    LayoutServiceUtil.updateLayout(
1374                            layoutPrototypeLayout.getGroupId(),
1375                            layoutPrototypeLayout.getPrivateLayout(),
1376                            layoutPrototypeLayout.getLayoutId(),
1377                            layoutPrototypeLayout.getTypeSettings());
1378            }
1379    
1380            /**
1381             * Sets the number of failed merge attempts for the layout set prototype to
1382             * a new value.
1383             *
1384             * @param  layoutSetPrototype the site template of the counter being updated
1385             * @param  newMergeFailCount the new value of the counter
1386             * @throws PortalException if no site was associated with the layout set
1387             *         prototype, if the user did not have permission to update the
1388             *         layout set prototype, or if a portal exception occurred
1389             * @throws SystemException if a system exception occurred
1390             */
1391            @Override
1392            public void setMergeFailCount(
1393                            LayoutSetPrototype layoutSetPrototype, int newMergeFailCount)
1394                    throws PortalException, SystemException {
1395    
1396                    LayoutSet layoutSetPrototypeLayoutSet =
1397                            layoutSetPrototype.getLayoutSet();
1398    
1399                    UnicodeProperties layoutSetPrototypeSettingsProperties =
1400                            layoutSetPrototypeLayoutSet.getSettingsProperties();
1401    
1402                    if (newMergeFailCount == 0) {
1403                            layoutSetPrototypeSettingsProperties.remove(MERGE_FAIL_COUNT);
1404                    }
1405                    else {
1406                            layoutSetPrototypeSettingsProperties.setProperty(
1407                                    MERGE_FAIL_COUNT, String.valueOf(newMergeFailCount));
1408                    }
1409    
1410                    LayoutSetServiceUtil.updateSettings(
1411                            layoutSetPrototypeLayoutSet.getGroupId(),
1412                            layoutSetPrototypeLayoutSet.getPrivateLayout(),
1413                            layoutSetPrototypeLayoutSet.getSettings());
1414            }
1415    
1416            @Override
1417            public void updateLayoutScopes(
1418                            long userId, Layout sourceLayout, Layout targetLayout,
1419                            PortletPreferences sourcePreferences,
1420                            PortletPreferences targetPreferences, String sourcePortletId,
1421                            String languageId)
1422                    throws Exception {
1423    
1424                    String scopeType = GetterUtil.getString(
1425                            sourcePreferences.getValue("lfrScopeType", null));
1426    
1427                    if (Validator.isNull(scopeType) || !scopeType.equals("layout")) {
1428                            return;
1429                    }
1430    
1431                    Layout targetScopeLayout =
1432                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1433                                    targetLayout.getUuid(), targetLayout.getGroupId(),
1434                                    targetLayout.isPrivateLayout());
1435    
1436                    if (!targetScopeLayout.hasScopeGroup()) {
1437                            GroupLocalServiceUtil.addGroup(
1438                                    userId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
1439                                    Layout.class.getName(), targetLayout.getPlid(),
1440                                    GroupConstants.DEFAULT_LIVE_GROUP_ID,
1441                                    targetLayout.getName(languageId), null, 0, true,
1442                                    GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, null, false,
1443                                    true, null);
1444                    }
1445    
1446                    String portletTitle = PortalUtil.getPortletTitle(
1447                            sourcePortletId, languageId);
1448    
1449                    String newPortletTitle = PortalUtil.getNewPortletTitle(
1450                            portletTitle, String.valueOf(sourceLayout.getLayoutId()),
1451                            targetLayout.getName(languageId));
1452    
1453                    targetPreferences.setValue(
1454                            "groupId", String.valueOf(targetLayout.getGroupId()));
1455                    targetPreferences.setValue("lfrScopeType", "layout");
1456                    targetPreferences.setValue(
1457                            "lfrScopeLayoutUuid", targetLayout.getUuid());
1458                    targetPreferences.setValue(
1459                            "portletSetupTitle_" + languageId, newPortletTitle);
1460                    targetPreferences.setValue(
1461                            "portletSetupUseCustomTitle", Boolean.TRUE.toString());
1462    
1463                    targetPreferences.store();
1464            }
1465    
1466            @Override
1467            public void updateLayoutSetPrototypesLinks(
1468                            Group group, long publicLayoutSetPrototypeId,
1469                            long privateLayoutSetPrototypeId,
1470                            boolean publicLayoutSetPrototypeLinkEnabled,
1471                            boolean privateLayoutSetPrototypeLinkEnabled)
1472                    throws Exception {
1473    
1474                    updateLayoutSetPrototypeLink(
1475                            group.getGroupId(), true, privateLayoutSetPrototypeId,
1476                            privateLayoutSetPrototypeLinkEnabled);
1477                    updateLayoutSetPrototypeLink(
1478                            group.getGroupId(), false, publicLayoutSetPrototypeId,
1479                            publicLayoutSetPrototypeLinkEnabled);
1480            }
1481    
1482            /**
1483             * Checks the permissions necessary for resetting the layout or site. If the
1484             * permissions are not sufficient, a {@link PortalException} is thrown.
1485             *
1486             * @param  group the site being checked for sufficient permissions
1487             * @param  layout the page being checked for sufficient permissions
1488             *         (optionally <code>null</code>). If <code>null</code>, the
1489             *         permissions are only checked for resetting the site.
1490             * @throws PortalException if the user did not have permission to update the
1491             *         layout or site, or if a portal exception occurred
1492             * @throws SystemException if a system exception occurred
1493             */
1494            protected void checkResetPrototypePermissions(Group group, Layout layout)
1495                    throws PortalException, SystemException {
1496    
1497                    PermissionChecker permissionChecker =
1498                            PermissionThreadLocal.getPermissionChecker();
1499    
1500                    if ((layout != null) &&
1501                            !LayoutPermissionUtil.contains(
1502                                    permissionChecker, layout, ActionKeys.UPDATE)) {
1503    
1504                            throw new PrincipalException();
1505                    }
1506                    else if (!group.isUser() &&
1507                                     !GroupPermissionUtil.contains(
1508                                            permissionChecker, group, ActionKeys.UPDATE)) {
1509    
1510                            throw new PrincipalException();
1511                    }
1512                    else if (group.isUser() &&
1513                                     (permissionChecker.getUserId() != group.getClassPK())) {
1514    
1515                            throw new PrincipalException();
1516                    }
1517            }
1518    
1519            protected void doMergeLayoutPrototypeLayout(Group group, Layout layout)
1520                    throws Exception {
1521    
1522                    if (!layout.isLayoutPrototypeLinkActive() ||
1523                            group.isLayoutPrototype() || group.hasStagingGroup()) {
1524    
1525                            return;
1526                    }
1527    
1528                    long lastMergeTime = GetterUtil.getLong(
1529                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
1530    
1531                    LayoutPrototype layoutPrototype =
1532                            LayoutPrototypeLocalServiceUtil.
1533                                    getLayoutPrototypeByUuidAndCompanyId(
1534                                            layout.getLayoutPrototypeUuid(), layout.getCompanyId());
1535    
1536                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
1537    
1538                    Date modifiedDate = layoutPrototypeLayout.getModifiedDate();
1539    
1540                    if (lastMergeTime >= modifiedDate.getTime()) {
1541                            return;
1542                    }
1543    
1544                    UnicodeProperties prototypeTypeSettingsProperties =
1545                            layoutPrototypeLayout.getTypeSettingsProperties();
1546    
1547                    int mergeFailCount = GetterUtil.getInteger(
1548                            prototypeTypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1549    
1550                    if (mergeFailCount >
1551                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
1552    
1553                            if (_log.isWarnEnabled()) {
1554                                    StringBundler sb = new StringBundler(6);
1555    
1556                                    sb.append("Merge not performed because the fail threshold ");
1557                                    sb.append("was reached for layoutPrototypeId ");
1558                                    sb.append(layoutPrototype.getLayoutPrototypeId());
1559                                    sb.append(" and layoutId ");
1560                                    sb.append(layoutPrototypeLayout.getLayoutId());
1561                                    sb.append(". Update the count in the database to try again.");
1562    
1563                                    _log.warn(sb.toString());
1564                            }
1565    
1566                            return;
1567                    }
1568    
1569                    String owner = PortalUUIDUtil.generate();
1570    
1571                    try {
1572                            Lock lock = LockLocalServiceUtil.lock(
1573                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1574                                    String.valueOf(layout.getPlid()), owner);
1575    
1576                            if (!owner.equals(lock.getOwner())) {
1577                                    Date createDate = lock.getCreateDate();
1578    
1579                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1580                                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1581    
1582                                            // Acquire lock if the lock is older than the lock max time
1583    
1584                                            lock = LockLocalServiceUtil.lock(
1585                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1586                                                    String.valueOf(layout.getPlid()), lock.getOwner(),
1587                                                    owner);
1588    
1589                                            // Check if acquiring the lock succeeded or if another
1590                                            // process has the lock
1591    
1592                                            if (!owner.equals(lock.getOwner())) {
1593                                                    return;
1594                                            }
1595                                    }
1596                                    else {
1597                                            return;
1598                                    }
1599                            }
1600                    }
1601                    catch (Exception e) {
1602                            return;
1603                    }
1604    
1605                    try {
1606                            applyLayoutPrototype(layoutPrototype, layout, true);
1607                    }
1608                    catch (Exception e) {
1609                            _log.error(e, e);
1610    
1611                            prototypeTypeSettingsProperties.setProperty(
1612                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1613    
1614                            // Invoke updateImpl so that we do not trigger the listeners
1615    
1616                            LayoutUtil.updateImpl(layoutPrototypeLayout);
1617                    }
1618                    finally {
1619                            LockLocalServiceUtil.unlock(
1620                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1621                                    String.valueOf(layout.getPlid()), owner);
1622                    }
1623            }
1624    
1625            /**
1626             * Resets the modified timestamp on the layout, and then calls {@link
1627             * #doResetPrototype(LayoutSet)} to reset the modified timestamp on the
1628             * layout's site.
1629             *
1630             * <p>
1631             * After the timestamps are reset, the modified page template and site
1632             * template are merged into their linked layout and site when they are first
1633             * accessed.
1634             * </p>
1635             *
1636             * @param  layout the page having its timestamp reset
1637             * @throws PortalException if no site was associated with the layout or if a
1638             *         portal exception occurred
1639             * @throws SystemException if a system exception occurred
1640             */
1641            protected void doResetPrototype(Layout layout)
1642                    throws PortalException, SystemException {
1643    
1644                    layout.setModifiedDate(null);
1645    
1646                    LayoutLocalServiceUtil.updateLayout(layout);
1647    
1648                    LayoutSet layoutSet = layout.getLayoutSet();
1649    
1650                    doResetPrototype(layoutSet);
1651            }
1652    
1653            /**
1654             * Resets the modified timestamp on the layout set.
1655             *
1656             * <p>
1657             * After the timestamp is reset, the modified site template is merged into
1658             * its linked layout set when it is first accessed.
1659             * </p>
1660             *
1661             * @param  layoutSet the site having its timestamp reset
1662             * @throws SystemException if a system exception occurred
1663             */
1664            protected void doResetPrototype(LayoutSet layoutSet)
1665                    throws SystemException {
1666    
1667                    UnicodeProperties settingsProperties =
1668                            layoutSet.getSettingsProperties();
1669    
1670                    settingsProperties.remove(LAST_MERGE_TIME);
1671    
1672                    settingsProperties.setProperty(
1673                            LAST_RESET_TIME, String.valueOf(System.currentTimeMillis()));
1674    
1675                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
1676            }
1677    
1678            protected Map<String, String[]> getLayoutSetPrototypesParameters(
1679                    boolean importData) {
1680    
1681                    Map<String, String[]> parameterMap =
1682                            new LinkedHashMap<String, String[]>();
1683    
1684                    parameterMap.put(
1685                            PortletDataHandlerKeys.CATEGORIES,
1686                            new String[] {Boolean.TRUE.toString()});
1687                    parameterMap.put(
1688                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1689                            new String[] {Boolean.FALSE.toString()});
1690                    parameterMap.put(
1691                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1692                            new String[] {Boolean.FALSE.toString()});
1693                    parameterMap.put(
1694                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
1695                            new String[] {Boolean.TRUE.toString()});
1696                    parameterMap.put(
1697                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
1698                            new String[] {Boolean.TRUE.toString()});
1699                    parameterMap.put(
1700                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1701                            new String[] {Boolean.TRUE.toString()});
1702                    parameterMap.put(
1703                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
1704                            new String[] {
1705                                    PortletDataHandlerKeys.
1706                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
1707                            });
1708                    parameterMap.put(
1709                            PortletDataHandlerKeys.LOGO,
1710                            new String[] {Boolean.TRUE.toString()});
1711                    parameterMap.put(
1712                            PortletDataHandlerKeys.PERMISSIONS,
1713                            new String[] {Boolean.TRUE.toString()});
1714                    parameterMap.put(
1715                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
1716                            new String[] {Boolean.TRUE.toString()});
1717                    parameterMap.put(
1718                            PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL,
1719                            new String[] {Boolean.TRUE.toString()});
1720                    parameterMap.put(
1721                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
1722                            new String[] {Boolean.TRUE.toString()});
1723                    parameterMap.put(
1724                            PortletDataHandlerKeys.THEME,
1725                            new String[] {Boolean.FALSE.toString()});
1726                    parameterMap.put(
1727                            PortletDataHandlerKeys.THEME_REFERENCE,
1728                            new String[] {Boolean.TRUE.toString()});
1729                    parameterMap.put(
1730                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1731                            new String[] {Boolean.FALSE.toString()});
1732                    parameterMap.put(
1733                            PortletDataHandlerKeys.USER_ID_STRATEGY,
1734                            new String[] {UserIdStrategy.CURRENT_USER_ID});
1735    
1736                    if (importData) {
1737                            parameterMap.put(
1738                                    PortletDataHandlerKeys.DATA_STRATEGY,
1739                                    new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
1740                            parameterMap.put(
1741                                    PortletDataHandlerKeys.PORTLET_DATA,
1742                                    new String[] {Boolean.TRUE.toString()});
1743                            parameterMap.put(
1744                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1745                                    new String[] {Boolean.TRUE.toString()});
1746                    }
1747                    else {
1748                            parameterMap.put(
1749                                    PortletDataHandlerKeys.PORTLET_DATA,
1750                                    new String[] {Boolean.FALSE.toString()});
1751                            parameterMap.put(
1752                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1753                                    new String[] {Boolean.FALSE.toString()});
1754                    }
1755    
1756                    return parameterMap;
1757            }
1758    
1759            protected void importLayoutSetPrototype(
1760                            LayoutSetPrototype layoutSetPrototype, long groupId,
1761                            boolean privateLayout, Map<String, String[]> parameterMap,
1762                            boolean importData)
1763                    throws PortalException, SystemException {
1764    
1765                    File file = null;
1766    
1767                    StringBundler sb = new StringBundler(importData ? 4 : 3);
1768    
1769                    sb.append(_TEMP_DIR);
1770                    sb.append(layoutSetPrototype.getUuid());
1771    
1772                    if (importData) {
1773                            sb.append("-data");
1774                    }
1775    
1776                    sb.append(".lar");
1777    
1778                    File cacheFile = new File(sb.toString());
1779    
1780                    if (cacheFile.exists()) {
1781                            Date modifiedDate = layoutSetPrototype.getModifiedDate();
1782    
1783                            if (cacheFile.lastModified() >= modifiedDate.getTime()) {
1784                                    if (_log.isDebugEnabled()) {
1785                                            _log.debug(
1786                                                    "Using cached layout set prototype LAR file " +
1787                                                            cacheFile.getAbsolutePath());
1788                                    }
1789    
1790                                    file = cacheFile;
1791                            }
1792                    }
1793    
1794                    boolean newFile = false;
1795    
1796                    if (file == null) {
1797                            file = LayoutLocalServiceUtil.exportLayoutsAsFile(
1798                                    layoutSetPrototype.getGroupId(), true, null, parameterMap, null,
1799                                    null);
1800    
1801                            newFile = true;
1802                    }
1803    
1804                    long userId = UserLocalServiceUtil.getDefaultUserId(
1805                            layoutSetPrototype.getCompanyId());
1806    
1807                    LayoutLocalServiceUtil.importLayouts(
1808                            userId, groupId, privateLayout, parameterMap, file);
1809    
1810                    if (newFile) {
1811                            try {
1812                                    FileUtil.copyFile(file, cacheFile);
1813    
1814                                    if (_log.isDebugEnabled()) {
1815                                            _log.debug(
1816                                                    "Copied " + file.getAbsolutePath() + " to " +
1817                                                            cacheFile.getAbsolutePath());
1818                                    }
1819                            }
1820                            catch (Exception e) {
1821                                    _log.error(
1822                                            "Unable to copy file " + file.getAbsolutePath() + " to " +
1823                                                    cacheFile.getAbsolutePath(),
1824                                            e);
1825                            }
1826                    }
1827            }
1828    
1829            protected void setLayoutSetPrototypeLinkEnabledParameter(
1830                    Map<String, String[]> parameterMap, LayoutSet targetLayoutSet,
1831                    ServiceContext serviceContext) {
1832    
1833                    PermissionChecker permissionChecker =
1834                            PermissionThreadLocal.getPermissionChecker();
1835    
1836                    if ((permissionChecker == null) ||
1837                            !PortalPermissionUtil.contains(
1838                                    permissionChecker, ActionKeys.UNLINK_LAYOUT_SET_PROTOTYPE)) {
1839    
1840                            return;
1841                    }
1842    
1843                    if (targetLayoutSet.isPrivateLayout()) {
1844                            boolean privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1845                                    serviceContext, "privateLayoutSetPrototypeLinkEnabled", true);
1846    
1847                            if (!privateLayoutSetPrototypeLinkEnabled) {
1848                                    privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1849                                            serviceContext, "layoutSetPrototypeLinkEnabled");
1850                            }
1851    
1852                            parameterMap.put(
1853                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1854                                    new String[] {
1855                                            String.valueOf(privateLayoutSetPrototypeLinkEnabled)
1856                                    });
1857                    }
1858                    else {
1859                            boolean publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1860                                    serviceContext, "publicLayoutSetPrototypeLinkEnabled");
1861    
1862                            if (!publicLayoutSetPrototypeLinkEnabled) {
1863                                    publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1864                                            serviceContext, "layoutSetPrototypeLinkEnabled", true);
1865                            }
1866    
1867                            parameterMap.put(
1868                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1869                                    new String[] {
1870                                            String.valueOf(publicLayoutSetPrototypeLinkEnabled)
1871                                    });
1872                    }
1873            }
1874    
1875            protected void updateLayoutSetPrototypeLink(
1876                            long groupId, boolean privateLayout, long layoutSetPrototypeId,
1877                            boolean layoutSetPrototypeLinkEnabled)
1878                    throws Exception {
1879    
1880                    String layoutSetPrototypeUuid = null;
1881    
1882                    if (layoutSetPrototypeId > 0) {
1883                            LayoutSetPrototype layoutSetPrototype =
1884                                    LayoutSetPrototypeLocalServiceUtil.fetchLayoutSetPrototype(
1885                                            layoutSetPrototypeId);
1886    
1887                            if (layoutSetPrototype != null) {
1888                                    layoutSetPrototypeUuid = layoutSetPrototype.getUuid();
1889    
1890                                    // Merge without enabling the link
1891    
1892                                    if (!layoutSetPrototypeLinkEnabled &&
1893                                            (layoutSetPrototypeId > 0)) {
1894    
1895                                            Map<String, String[]> parameterMap =
1896                                                    getLayoutSetPrototypesParameters(true);
1897    
1898                                            importLayoutSetPrototype(
1899                                                    layoutSetPrototype, groupId, privateLayout,
1900                                                    parameterMap, true);
1901                                    }
1902                            }
1903                    }
1904    
1905                    LayoutSetServiceUtil.updateLayoutSetPrototypeLinkEnabled(
1906                            groupId, privateLayout, layoutSetPrototypeLinkEnabled,
1907                            layoutSetPrototypeUuid);
1908    
1909                    LayoutLocalServiceUtil.updatePriorities(groupId, privateLayout);
1910            }
1911    
1912            private static final String _TEMP_DIR =
1913                    SystemProperties.get(SystemProperties.TMP_DIR) +
1914                            "/liferay/layout_set_prototype/";
1915    
1916            private static Log _log = LogFactoryUtil.getLog(SitesImpl.class);
1917    
1918    }