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                    List<Role> roles = RoleLocalServiceUtil.getGroupRelatedRoles(
330                            targetLayout.getGroupId());
331    
332                    LayoutTypePortlet sourceLayoutTypePortlet =
333                            (LayoutTypePortlet)sourceLayout.getLayoutType();
334    
335                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
336    
337                    for (String sourcePortletId : sourcePortletIds) {
338                            String resourceName = PortletConstants.getRootPortletId(
339                                    sourcePortletId);
340    
341                            String sourceResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
342                                    sourceLayout.getPlid(), sourcePortletId);
343    
344                            String targetResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
345                                    targetLayout.getPlid(), sourcePortletId);
346    
347                            List<String> actionIds =
348                                    ResourceActionsUtil.getPortletResourceActions(resourceName);
349    
350                            for (Role role : roles) {
351                                    String roleName = role.getName();
352    
353                                    if (roleName.equals(RoleConstants.ADMINISTRATOR) ||
354                                            (targetLayout.isPrivateLayout() &&
355                                             roleName.equals(RoleConstants.GUEST))) {
356    
357                                            continue;
358                                    }
359    
360                                    List<String> actions =
361                                            ResourcePermissionLocalServiceUtil.
362                                                    getAvailableResourcePermissionActionIds(
363                                                            targetLayout.getCompanyId(), resourceName,
364                                                            ResourceConstants.SCOPE_INDIVIDUAL,
365                                                            sourceResourcePrimKey, role.getRoleId(), actionIds);
366    
367                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
368                                            targetLayout.getCompanyId(), resourceName,
369                                            ResourceConstants.SCOPE_INDIVIDUAL, targetResourcePrimKey,
370                                            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_REFERENCE,
671                            new String[] {Boolean.TRUE.toString()});
672                    parameterMap.put(
673                            PortletDataHandlerKeys.USER_ID_STRATEGY,
674                            new String[] {UserIdStrategy.CURRENT_USER_ID});
675    
676                    return parameterMap;
677            }
678    
679            /**
680             * Returns the number of failed merge attempts for the layout prototype
681             * since its last reset or update.
682             *
683             * @param  layoutPrototype the page template being checked for failed merge
684             *         attempts
685             * @return the number of failed merge attempts for the layout prototype
686             * @throws PortalException if no page was associated with the layout
687             *         prototype or if a portal exception occurred
688             * @throws SystemException if a system exception occurred
689             */
690            @Override
691            public int getMergeFailCount(LayoutPrototype layoutPrototype)
692                    throws PortalException, SystemException {
693    
694                    if ((layoutPrototype == null) ||
695                            (layoutPrototype.getLayoutPrototypeId() == 0)) {
696    
697                            return 0;
698                    }
699    
700                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
701    
702                    UnicodeProperties prototypeTypeSettingsProperties =
703                            layoutPrototypeLayout.getTypeSettingsProperties();
704    
705                    return GetterUtil.getInteger(
706                            prototypeTypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
707            }
708    
709            /**
710             * Returns the number of failed merge attempts for the layout set prototype
711             * since its last reset or update.
712             *
713             * @param  layoutSetPrototype the site template being checked for failed
714             *         merge attempts
715             * @return the number of failed merge attempts for the layout set prototype
716             * @throws PortalException if no site was associated with the layout set
717             *         prototype or if a portal exception occurred
718             * @throws SystemException if a system exception occurred
719             */
720            @Override
721            public int getMergeFailCount(LayoutSetPrototype layoutSetPrototype)
722                    throws PortalException, SystemException {
723    
724                    if ((layoutSetPrototype == null) ||
725                            (layoutSetPrototype.getLayoutSetPrototypeId() == 0)) {
726    
727                            return 0;
728                    }
729    
730                    LayoutSet layoutSetPrototypeLayoutSet =
731                            layoutSetPrototype.getLayoutSet();
732    
733                    UnicodeProperties layoutSetPrototypeSettingsProperties =
734                            layoutSetPrototypeLayoutSet.getSettingsProperties();
735    
736                    return GetterUtil.getInteger(
737                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
738            }
739    
740            @Override
741            public List<Layout> getMergeFailFriendlyURLLayouts(LayoutSet layoutSet)
742                    throws PortalException, SystemException {
743    
744                    if (layoutSet == null) {
745                            return Collections.emptyList();
746                    }
747    
748                    UnicodeProperties settingsProperties =
749                            layoutSet.getSettingsProperties();
750    
751                    String uuids = settingsProperties.getProperty(
752                            MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
753    
754                    if (Validator.isNotNull(uuids)) {
755                            List<Layout> layouts = new ArrayList<Layout>();
756    
757                            for (String uuid : StringUtil.split(uuids)) {
758                                    Layout layout =
759                                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
760                                                    uuid, layoutSet.getGroupId(),
761                                                    layoutSet.isPrivateLayout());
762    
763                                    layouts.add(layout);
764                            }
765    
766                            return layouts;
767                    }
768    
769                    return Collections.emptyList();
770            }
771    
772            @Override
773            public void importLayoutSetPrototype(
774                            LayoutSetPrototype layoutSetPrototype, InputStream inputStream,
775                            ServiceContext serviceContext)
776                    throws PortalException, SystemException {
777    
778                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
779    
780                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
781                            serviceContext);
782    
783                    setLayoutSetPrototypeLinkEnabledParameter(
784                            parameterMap, layoutSet, serviceContext);
785    
786                    LayoutServiceUtil.importLayouts(
787                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), parameterMap,
788                            inputStream);
789            }
790    
791            @Override
792            public boolean isContentSharingWithChildrenEnabled(Group group)
793                    throws SystemException {
794    
795                    UnicodeProperties typeSettingsProperties =
796                            group.getParentLiveGroupTypeSettingsProperties();
797    
798                    int companyContentSharingEnabled = PrefsPropsUtil.getInteger(
799                            group.getCompanyId(),
800                            PropsKeys.SITES_CONTENT_SHARING_WITH_CHILDREN_ENABLED);
801    
802                    if (companyContentSharingEnabled ==
803                                    CONTENT_SHARING_WITH_CHILDREN_DISABLED) {
804    
805                            return false;
806                    }
807    
808                    int groupContentSharingEnabled = GetterUtil.getInteger(
809                            typeSettingsProperties.getProperty(
810                                    "contentSharingWithChildrenEnabled"),
811                                    CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE);
812    
813                    if ((groupContentSharingEnabled ==
814                                    CONTENT_SHARING_WITH_CHILDREN_ENABLED) ||
815                            ((companyContentSharingEnabled ==
816                                    CONTENT_SHARING_WITH_CHILDREN_ENABLED_BY_DEFAULT) &&
817                             (groupContentSharingEnabled ==
818                                    CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE))) {
819    
820                            return true;
821                    }
822    
823                    return false;
824            }
825    
826            @Override
827            public boolean isFirstLayout(
828                            long groupId, boolean privateLayout, long layoutId)
829                    throws SystemException {
830    
831                    Layout firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
832                            groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
833    
834                    if ((firstLayout != null) && (firstLayout.getLayoutId() == layoutId )) {
835                            return true;
836                    }
837    
838                    return false;
839            }
840    
841            @Override
842            public boolean isLayoutDeleteable(Layout layout) {
843                    try {
844                            if (layout instanceof VirtualLayout) {
845                                    return false;
846                            }
847    
848                            if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
849                                    return true;
850                            }
851    
852                            LayoutSet layoutSet = layout.getLayoutSet();
853    
854                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
855                                    return true;
856                            }
857    
858                            if (LayoutLocalServiceUtil.hasLayoutSetPrototypeLayout(
859                                            layoutSet.getLayoutSetPrototypeUuid(),
860                                            layout.getCompanyId(),
861                                            layout.getSourcePrototypeLayoutUuid())) {
862    
863                                    return false;
864                            }
865                    }
866                    catch (Exception e) {
867                            if (_log.isDebugEnabled()) {
868                                    _log.debug(e, e);
869                            }
870                    }
871    
872                    return true;
873            }
874    
875            @Override
876            public boolean isLayoutModifiedSinceLastMerge(Layout layout) {
877                    if ((layout == null) ||
878                            Validator.isNull(layout.getSourcePrototypeLayoutUuid()) ||
879                            layout.isLayoutPrototypeLinkActive() ||
880                            !isLayoutUpdateable(layout)) {
881    
882                            return false;
883                    }
884    
885                    long lastMergeTime = GetterUtil.getLong(
886                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
887    
888                    Date existingLayoutModifiedDate = layout.getModifiedDate();
889    
890                    if ((existingLayoutModifiedDate != null) &&
891                            (existingLayoutModifiedDate.getTime() > lastMergeTime)) {
892    
893                            return true;
894                    }
895    
896                    return false;
897            }
898    
899            /**
900             * Returns <code>true</code> if the linked site template can be merged into
901             * the layout set. This method checks the current number of merge fail
902             * attempts stored for the linked site template and, if greater than the
903             * merge fail threshold, will return <code>false</code>.
904             *
905             * @param  group the site template's group, which is about to be merged into
906             *         the layout set
907             * @param  layoutSet the site in which the site template is attempting to
908             *         merge into
909             * @return <code>true</code> if the linked site template can be merged into
910             *         the layout set; <code>false</code> otherwise
911             * @throws PortalException if no site template was associated with the
912             *         layout set or if a portal exception occurred
913             * @throws SystemException if a system exception occurred
914             */
915            @Override
916            public boolean isLayoutSetMergeable(Group group, LayoutSet layoutSet)
917                    throws PortalException, SystemException {
918    
919                    if (!layoutSet.isLayoutSetPrototypeLinkActive() ||
920                            group.isLayoutPrototype() || group.isLayoutSetPrototype()) {
921    
922                            return false;
923                    }
924    
925                    UnicodeProperties settingsProperties =
926                            layoutSet.getSettingsProperties();
927    
928                    long lastMergeTime = GetterUtil.getLong(
929                            settingsProperties.getProperty(LAST_MERGE_TIME));
930    
931                    LayoutSetPrototype layoutSetPrototype =
932                            LayoutSetPrototypeLocalServiceUtil.
933                                    getLayoutSetPrototypeByUuidAndCompanyId(
934                                            layoutSet.getLayoutSetPrototypeUuid(),
935                                            layoutSet.getCompanyId());
936    
937                    Date modifiedDate = layoutSetPrototype.getModifiedDate();
938    
939                    if (lastMergeTime >= modifiedDate.getTime()) {
940                            return false;
941                    }
942    
943                    LayoutSet layoutSetPrototypeLayoutSet =
944                            layoutSetPrototype.getLayoutSet();
945    
946                    UnicodeProperties layoutSetPrototypeSettingsProperties =
947                            layoutSetPrototypeLayoutSet.getSettingsProperties();
948    
949                    int mergeFailCount = GetterUtil.getInteger(
950                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
951    
952                    if (mergeFailCount >
953                                    PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
954    
955                            if (_log.isWarnEnabled()) {
956                                    StringBundler sb = new StringBundler(6);
957    
958                                    sb.append("Merge not performed because the fail threshold ");
959                                    sb.append("was reached for layoutSetPrototypeId ");
960                                    sb.append(layoutSetPrototype.getLayoutSetPrototypeId());
961                                    sb.append(" and layoutId ");
962                                    sb.append(layoutSetPrototypeLayoutSet.getLayoutSetId());
963                                    sb.append(". Update the count in the database to try again.");
964    
965                                    _log.warn(sb.toString());
966                            }
967    
968                            return false;
969                    }
970    
971                    return true;
972            }
973    
974            @Override
975            public boolean isLayoutSetPrototypeUpdateable(LayoutSet layoutSet) {
976                    if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
977                            return true;
978                    }
979    
980                    try {
981                            LayoutSetPrototype layoutSetPrototype =
982                                    LayoutSetPrototypeLocalServiceUtil.
983                                            getLayoutSetPrototypeByUuidAndCompanyId(
984                                                    layoutSet.getLayoutSetPrototypeUuid(),
985                                                    layoutSet.getCompanyId());
986    
987                            String layoutsUpdateable = layoutSetPrototype.getSettingsProperty(
988                                    "layoutsUpdateable");
989    
990                            if (Validator.isNotNull(layoutsUpdateable)) {
991                                    return GetterUtil.getBoolean(layoutsUpdateable, true);
992                            }
993                    }
994                    catch (Exception e) {
995                            if (_log.isDebugEnabled()) {
996                                    _log.debug(e, e);
997                            }
998                    }
999    
1000                    return true;
1001            }
1002    
1003            @Override
1004            public boolean isLayoutSortable(Layout layout) {
1005                    return isLayoutDeleteable(layout);
1006            }
1007    
1008            @Override
1009            public boolean isLayoutUpdateable(Layout layout) {
1010                    try {
1011                            if (layout instanceof VirtualLayout) {
1012                                    return false;
1013                            }
1014    
1015                            if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
1016                                    Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
1017    
1018                                    return true;
1019                            }
1020    
1021                            LayoutSet layoutSet = layout.getLayoutSet();
1022    
1023                            if (layoutSet.isLayoutSetPrototypeLinkActive()) {
1024                                    boolean layoutSetPrototypeUpdateable =
1025                                            isLayoutSetPrototypeUpdateable(layoutSet);
1026    
1027                                    if (!layoutSetPrototypeUpdateable) {
1028                                            return false;
1029                                    }
1030    
1031                                    Layout layoutSetPrototypeLayout = getLayoutSetPrototypeLayout(
1032                                            layout);
1033    
1034                                    String layoutUpdateable =
1035                                            layoutSetPrototypeLayout.getTypeSettingsProperty(
1036                                                    LAYOUT_UPDATEABLE);
1037    
1038                                    if (Validator.isNull(layoutUpdateable)) {
1039                                            return true;
1040                                    }
1041    
1042                                    return GetterUtil.getBoolean(layoutUpdateable);
1043                            }
1044                    }
1045                    catch (Exception e) {
1046                            if (_log.isDebugEnabled()) {
1047                                    _log.debug(e, e);
1048                            }
1049                    }
1050    
1051                    return true;
1052            }
1053    
1054            @Override
1055            public boolean isOrganizationUser(
1056                            long companyId, Group group, User user,
1057                            List<String> organizationNames)
1058                    throws Exception {
1059    
1060                    boolean organizationUser = false;
1061    
1062                    LinkedHashMap<String, Object> organizationParams =
1063                            new LinkedHashMap<String, Object>();
1064    
1065                    organizationParams.put(
1066                            "groupOrganization", new Long(group.getGroupId()));
1067                    organizationParams.put(
1068                            "organizationsGroups", new Long(group.getGroupId()));
1069    
1070                    List<Organization> organizationsGroups =
1071                            OrganizationLocalServiceUtil.search(
1072                                    companyId, OrganizationConstants.ANY_PARENT_ORGANIZATION_ID,
1073                                    null, null, null, null, organizationParams, QueryUtil.ALL_POS,
1074                                    QueryUtil.ALL_POS);
1075    
1076                    for (Organization organization : organizationsGroups) {
1077                            for (long userOrganizationId : user.getOrganizationIds()) {
1078                                    if (userOrganizationId == organization.getOrganizationId()) {
1079                                            organizationNames.add(organization.getName());
1080    
1081                                            organizationUser = true;
1082                                    }
1083                            }
1084                    }
1085    
1086                    return organizationUser;
1087            }
1088    
1089            @Override
1090            public boolean isUserGroupLayoutSetViewable(
1091                            PermissionChecker permissionChecker, Group userGroupGroup)
1092                    throws PortalException, SystemException {
1093    
1094                    if (!userGroupGroup.isUserGroup()) {
1095                            return false;
1096                    }
1097    
1098                    if (GroupPermissionUtil.contains(
1099                                    permissionChecker, userGroupGroup.getGroupId(),
1100                                    ActionKeys.VIEW)) {
1101    
1102                            return true;
1103                    }
1104    
1105                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
1106                            userGroupGroup.getClassPK());
1107    
1108                    if (UserLocalServiceUtil.hasUserGroupUser(
1109                                    userGroup.getUserGroupId(), permissionChecker.getUserId())) {
1110    
1111                            return true;
1112                    }
1113                    else {
1114                            return false;
1115                    }
1116            }
1117    
1118            @Override
1119            public boolean isUserGroupUser(
1120                            long companyId, Group group, User user, List<String> userGroupNames)
1121                    throws Exception {
1122    
1123                    boolean userGroupUser = false;
1124    
1125                    LinkedHashMap<String, Object> userGroupParams =
1126                            new LinkedHashMap<String, Object>();
1127    
1128                    userGroupParams.put("userGroupsGroups", new Long(group.getGroupId()));
1129    
1130                    List<UserGroup> userGroupsGroups = UserGroupLocalServiceUtil.search(
1131                            companyId, null, userGroupParams, QueryUtil.ALL_POS,
1132                            QueryUtil.ALL_POS, (OrderByComparator)null);
1133    
1134                    for (UserGroup userGroup : userGroupsGroups) {
1135                            for (long userGroupId : user.getUserGroupIds()) {
1136                                    if (userGroupId == userGroup.getUserGroupId()) {
1137                                            userGroupNames.add(userGroup.getName());
1138    
1139                                            userGroupUser = true;
1140                                    }
1141                            }
1142                    }
1143    
1144                    return userGroupUser;
1145            }
1146    
1147            @Override
1148            public void mergeLayoutPrototypeLayout(Group group, Layout layout)
1149                    throws Exception {
1150    
1151                    String sourcePrototypeLayoutUuid =
1152                            layout.getSourcePrototypeLayoutUuid();
1153    
1154                    if (Validator.isNull(sourcePrototypeLayoutUuid)) {
1155                            doMergeLayoutPrototypeLayout(group, layout);
1156    
1157                            return;
1158                    }
1159    
1160                    LayoutSet layoutSet = layout.getLayoutSet();
1161    
1162                    long layoutSetPrototypeId = layoutSet.getLayoutSetPrototypeId();
1163    
1164                    if (layoutSetPrototypeId > 0) {
1165                            Group layoutSetPrototypeGroup =
1166                                    GroupLocalServiceUtil.getLayoutSetPrototypeGroup(
1167                                            layout.getCompanyId(), layoutSetPrototypeId);
1168    
1169                            Layout sourcePrototypeLayout =
1170                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1171                                            sourcePrototypeLayoutUuid,
1172                                            layoutSetPrototypeGroup.getGroupId(), true);
1173    
1174                            doMergeLayoutPrototypeLayout(
1175                                    layoutSetPrototypeGroup, sourcePrototypeLayout);
1176                    }
1177    
1178                    doMergeLayoutPrototypeLayout(group, layout);
1179            }
1180    
1181            /**
1182             * @deprecated As of 6.2.0, replaced by {@link
1183             *             #mergeLayoutPrototypeLayout(Group, Layout)}
1184             */
1185            @Override
1186            public void mergeLayoutProtypeLayout(Group group, Layout layout)
1187                    throws Exception {
1188    
1189                    mergeLayoutPrototypeLayout(group, layout);
1190            }
1191    
1192            @Override
1193            public void mergeLayoutSetPrototypeLayouts(Group group, LayoutSet layoutSet)
1194                    throws Exception {
1195    
1196                    if (!isLayoutSetMergeable(group, layoutSet)) {
1197                            return;
1198                    }
1199    
1200                    UnicodeProperties settingsProperties =
1201                            layoutSet.getSettingsProperties();
1202    
1203                    long lastMergeTime = GetterUtil.getLong(
1204                            settingsProperties.getProperty(LAST_MERGE_TIME));
1205    
1206                    LayoutSetPrototype layoutSetPrototype =
1207                            LayoutSetPrototypeLocalServiceUtil.
1208                                    getLayoutSetPrototypeByUuidAndCompanyId(
1209                                            layoutSet.getLayoutSetPrototypeUuid(),
1210                                            layoutSet.getCompanyId());
1211    
1212                    LayoutSet layoutSetPrototypeLayoutSet =
1213                            layoutSetPrototype.getLayoutSet();
1214    
1215                    UnicodeProperties layoutSetPrototypeSettingsProperties =
1216                            layoutSetPrototypeLayoutSet.getSettingsProperties();
1217    
1218                    int mergeFailCount = GetterUtil.getInteger(
1219                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1220    
1221                    String owner = PortalUUIDUtil.generate();
1222    
1223                    try {
1224                            Lock lock = LockLocalServiceUtil.lock(
1225                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1226                                    String.valueOf(layoutSet.getLayoutSetId()), owner);
1227    
1228                            // Double deep check
1229    
1230                            if (!owner.equals(lock.getOwner())) {
1231                                    Date createDate = lock.getCreateDate();
1232    
1233                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1234                                                    PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1235    
1236                                            // Acquire lock if the lock is older than the lock max time
1237    
1238                                            lock = LockLocalServiceUtil.lock(
1239                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1240                                                    String.valueOf(layoutSet.getLayoutSetId()),
1241                                                    lock.getOwner(), owner);
1242    
1243                                            // Check if acquiring the lock succeeded or if another
1244                                            // process has the lock
1245    
1246                                            if (!owner.equals(lock.getOwner())) {
1247                                                    return;
1248                                            }
1249                                    }
1250                                    else {
1251                                            return;
1252                                    }
1253                            }
1254                    }
1255                    catch (Exception e) {
1256                            return;
1257                    }
1258    
1259                    try {
1260                            boolean importData = true;
1261    
1262                            long lastResetTime = GetterUtil.getLong(
1263                                    settingsProperties.getProperty(LAST_RESET_TIME));
1264    
1265                            if ((lastMergeTime > 0) || (lastResetTime > 0)) {
1266                                    importData = false;
1267                            }
1268    
1269                            Map<String, String[]> parameterMap =
1270                                    getLayoutSetPrototypesParameters(importData);
1271    
1272                            removeMergeFailFriendlyURLLayouts(layoutSet);
1273    
1274                            importLayoutSetPrototype(
1275                                    layoutSetPrototype, layoutSet.getGroupId(),
1276                                    layoutSet.isPrivateLayout(), parameterMap, importData);
1277                    }
1278                    catch (Exception e) {
1279                            _log.error(e, e);
1280    
1281                            layoutSetPrototypeSettingsProperties.setProperty(
1282                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1283    
1284                            // Invoke updateImpl so that we do not trigger the listeners
1285    
1286                            LayoutSetUtil.updateImpl(layoutSetPrototypeLayoutSet);
1287                    }
1288                    finally {
1289                            LockLocalServiceUtil.unlock(
1290                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1291                                    String.valueOf(layoutSet.getLayoutSetId()), owner);
1292                    }
1293            }
1294    
1295            /**
1296             * @deprecated As of 6.2.0, replaced by {@link
1297             *             #mergeLayoutSetPrototypeLayouts(Group, LayoutSet)}
1298             */
1299            @Override
1300            public void mergeLayoutSetProtypeLayouts(Group group, LayoutSet layoutSet)
1301                    throws Exception {
1302    
1303                    mergeLayoutSetPrototypeLayouts(group, layoutSet);
1304            }
1305    
1306            @Override
1307            public void removeMergeFailFriendlyURLLayouts(LayoutSet layoutSet)
1308                    throws SystemException {
1309    
1310                    UnicodeProperties settingsProperties =
1311                            layoutSet.getSettingsProperties();
1312    
1313                    settingsProperties.remove(MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
1314    
1315                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
1316            }
1317    
1318            /**
1319             * Checks the permissions necessary for resetting the layout. If sufficient,
1320             * the layout is reset by calling {@link #doResetPrototype(Layout)}.
1321             *
1322             * @param  layout the page being checked for sufficient permissions
1323             * @throws PortalException if no site was associated with the layout, if the
1324             *         user did not have permission to update the layout or the layout's
1325             *         site, or if a portal exception occurred
1326             * @throws SystemException if a system exception occurred
1327             */
1328            @Override
1329            public void resetPrototype(Layout layout)
1330                    throws PortalException, SystemException {
1331    
1332                    checkResetPrototypePermissions(layout.getGroup(), layout);
1333    
1334                    doResetPrototype(layout);
1335            }
1336    
1337            /**
1338             * Checks the permissions necessary for resetting the layout set. If
1339             * sufficient, the layout set is reset by calling {@link
1340             * #doResetPrototype(LayoutSet)}.
1341             *
1342             * @param  layoutSet the site being checked for sufficient permissions
1343             * @throws PortalException if the user did not have permission to update the
1344             *         site or if a portal exception occurred
1345             * @throws SystemException if a system exception occurred
1346             */
1347            @Override
1348            public void resetPrototype(LayoutSet layoutSet)
1349                    throws PortalException, SystemException {
1350    
1351                    checkResetPrototypePermissions(layoutSet.getGroup(), null);
1352    
1353                    doResetPrototype(layoutSet);
1354            }
1355    
1356            /**
1357             * Sets the number of failed merge attempts for the layout prototype to a
1358             * new value.
1359             *
1360             * @param  layoutPrototype the page template of the counter being updated
1361             * @param  newMergeFailCount the new value of the counter
1362             * @throws PortalException if no page was associated with the layout
1363             *         prototype, if the user did not have permission to update the
1364             *         page, or if a portal exception occurred
1365             * @throws SystemException if a system exception occurred
1366             */
1367            @Override
1368            public void setMergeFailCount(
1369                            LayoutPrototype layoutPrototype, int newMergeFailCount)
1370                    throws PortalException, SystemException {
1371    
1372                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
1373    
1374                    UnicodeProperties prototypeTypeSettingsProperties =
1375                            layoutPrototypeLayout.getTypeSettingsProperties();
1376    
1377                    if (newMergeFailCount == 0) {
1378                            prototypeTypeSettingsProperties.remove(MERGE_FAIL_COUNT);
1379                    }
1380                    else {
1381                            prototypeTypeSettingsProperties.setProperty(
1382                                    MERGE_FAIL_COUNT, String.valueOf(newMergeFailCount));
1383                    }
1384    
1385                    LayoutServiceUtil.updateLayout(
1386                            layoutPrototypeLayout.getGroupId(),
1387                            layoutPrototypeLayout.getPrivateLayout(),
1388                            layoutPrototypeLayout.getLayoutId(),
1389                            layoutPrototypeLayout.getTypeSettings());
1390            }
1391    
1392            /**
1393             * Sets the number of failed merge attempts for the layout set prototype to
1394             * a new value.
1395             *
1396             * @param  layoutSetPrototype the site template of the counter being updated
1397             * @param  newMergeFailCount the new value of the counter
1398             * @throws PortalException if no site was associated with the layout set
1399             *         prototype, if the user did not have permission to update the
1400             *         layout set prototype, or if a portal exception occurred
1401             * @throws SystemException if a system exception occurred
1402             */
1403            @Override
1404            public void setMergeFailCount(
1405                            LayoutSetPrototype layoutSetPrototype, int newMergeFailCount)
1406                    throws PortalException, SystemException {
1407    
1408                    LayoutSet layoutSetPrototypeLayoutSet =
1409                            layoutSetPrototype.getLayoutSet();
1410    
1411                    UnicodeProperties layoutSetPrototypeSettingsProperties =
1412                            layoutSetPrototypeLayoutSet.getSettingsProperties();
1413    
1414                    if (newMergeFailCount == 0) {
1415                            layoutSetPrototypeSettingsProperties.remove(MERGE_FAIL_COUNT);
1416                    }
1417                    else {
1418                            layoutSetPrototypeSettingsProperties.setProperty(
1419                                    MERGE_FAIL_COUNT, String.valueOf(newMergeFailCount));
1420                    }
1421    
1422                    LayoutSetServiceUtil.updateSettings(
1423                            layoutSetPrototypeLayoutSet.getGroupId(),
1424                            layoutSetPrototypeLayoutSet.getPrivateLayout(),
1425                            layoutSetPrototypeLayoutSet.getSettings());
1426            }
1427    
1428            @Override
1429            public void updateLayoutScopes(
1430                            long userId, Layout sourceLayout, Layout targetLayout,
1431                            PortletPreferences sourcePreferences,
1432                            PortletPreferences targetPreferences, String sourcePortletId,
1433                            String languageId)
1434                    throws Exception {
1435    
1436                    String scopeType = GetterUtil.getString(
1437                            sourcePreferences.getValue("lfrScopeType", null));
1438    
1439                    if (Validator.isNull(scopeType) || !scopeType.equals("layout")) {
1440                            return;
1441                    }
1442    
1443                    Layout targetScopeLayout =
1444                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1445                                    targetLayout.getUuid(), targetLayout.getGroupId(),
1446                                    targetLayout.isPrivateLayout());
1447    
1448                    if (!targetScopeLayout.hasScopeGroup()) {
1449                            GroupLocalServiceUtil.addGroup(
1450                                    userId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
1451                                    Layout.class.getName(), targetLayout.getPlid(),
1452                                    GroupConstants.DEFAULT_LIVE_GROUP_ID,
1453                                    targetLayout.getName(languageId), null, 0, true,
1454                                    GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, null, false,
1455                                    true, null);
1456                    }
1457    
1458                    String portletTitle = PortalUtil.getPortletTitle(
1459                            sourcePortletId, languageId);
1460    
1461                    String newPortletTitle = PortalUtil.getNewPortletTitle(
1462                            portletTitle, String.valueOf(sourceLayout.getLayoutId()),
1463                            targetLayout.getName(languageId));
1464    
1465                    targetPreferences.setValue(
1466                            "groupId", String.valueOf(targetLayout.getGroupId()));
1467                    targetPreferences.setValue("lfrScopeType", "layout");
1468                    targetPreferences.setValue(
1469                            "lfrScopeLayoutUuid", targetLayout.getUuid());
1470                    targetPreferences.setValue(
1471                            "portletSetupTitle_" + languageId, newPortletTitle);
1472                    targetPreferences.setValue(
1473                            "portletSetupUseCustomTitle", Boolean.TRUE.toString());
1474    
1475                    targetPreferences.store();
1476            }
1477    
1478            @Override
1479            public void updateLayoutSetPrototypesLinks(
1480                            Group group, long publicLayoutSetPrototypeId,
1481                            long privateLayoutSetPrototypeId,
1482                            boolean publicLayoutSetPrototypeLinkEnabled,
1483                            boolean privateLayoutSetPrototypeLinkEnabled)
1484                    throws Exception {
1485    
1486                    updateLayoutSetPrototypeLink(
1487                            group.getGroupId(), true, privateLayoutSetPrototypeId,
1488                            privateLayoutSetPrototypeLinkEnabled);
1489                    updateLayoutSetPrototypeLink(
1490                            group.getGroupId(), false, publicLayoutSetPrototypeId,
1491                            publicLayoutSetPrototypeLinkEnabled);
1492            }
1493    
1494            /**
1495             * Checks the permissions necessary for resetting the layout or site. If the
1496             * permissions are not sufficient, a {@link PortalException} is thrown.
1497             *
1498             * @param  group the site being checked for sufficient permissions
1499             * @param  layout the page being checked for sufficient permissions
1500             *         (optionally <code>null</code>). If <code>null</code>, the
1501             *         permissions are only checked for resetting the site.
1502             * @throws PortalException if the user did not have permission to update the
1503             *         layout or site, or if a portal exception occurred
1504             * @throws SystemException if a system exception occurred
1505             */
1506            protected void checkResetPrototypePermissions(Group group, Layout layout)
1507                    throws PortalException, SystemException {
1508    
1509                    PermissionChecker permissionChecker =
1510                            PermissionThreadLocal.getPermissionChecker();
1511    
1512                    if ((layout != null) &&
1513                            !LayoutPermissionUtil.contains(
1514                                    permissionChecker, layout, ActionKeys.UPDATE)) {
1515    
1516                            throw new PrincipalException();
1517                    }
1518                    else if (!group.isUser() &&
1519                                     !GroupPermissionUtil.contains(
1520                                            permissionChecker, group, ActionKeys.UPDATE)) {
1521    
1522                            throw new PrincipalException();
1523                    }
1524                    else if (group.isUser() &&
1525                                     (permissionChecker.getUserId() != group.getClassPK())) {
1526    
1527                            throw new PrincipalException();
1528                    }
1529            }
1530    
1531            protected void doMergeLayoutPrototypeLayout(Group group, Layout layout)
1532                    throws Exception {
1533    
1534                    if (!layout.isLayoutPrototypeLinkActive() ||
1535                            group.isLayoutPrototype() || group.hasStagingGroup()) {
1536    
1537                            return;
1538                    }
1539    
1540                    long lastMergeTime = GetterUtil.getLong(
1541                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
1542    
1543                    LayoutPrototype layoutPrototype =
1544                            LayoutPrototypeLocalServiceUtil.
1545                                    getLayoutPrototypeByUuidAndCompanyId(
1546                                            layout.getLayoutPrototypeUuid(), layout.getCompanyId());
1547    
1548                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
1549    
1550                    Date modifiedDate = layoutPrototypeLayout.getModifiedDate();
1551    
1552                    if (lastMergeTime >= modifiedDate.getTime()) {
1553                            return;
1554                    }
1555    
1556                    UnicodeProperties prototypeTypeSettingsProperties =
1557                            layoutPrototypeLayout.getTypeSettingsProperties();
1558    
1559                    int mergeFailCount = GetterUtil.getInteger(
1560                            prototypeTypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1561    
1562                    if (mergeFailCount >
1563                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
1564    
1565                            if (_log.isWarnEnabled()) {
1566                                    StringBundler sb = new StringBundler(6);
1567    
1568                                    sb.append("Merge not performed because the fail threshold ");
1569                                    sb.append("was reached for layoutPrototypeId ");
1570                                    sb.append(layoutPrototype.getLayoutPrototypeId());
1571                                    sb.append(" and layoutId ");
1572                                    sb.append(layoutPrototypeLayout.getLayoutId());
1573                                    sb.append(". Update the count in the database to try again.");
1574    
1575                                    _log.warn(sb.toString());
1576                            }
1577    
1578                            return;
1579                    }
1580    
1581                    String owner = PortalUUIDUtil.generate();
1582    
1583                    try {
1584                            Lock lock = LockLocalServiceUtil.lock(
1585                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1586                                    String.valueOf(layout.getPlid()), owner);
1587    
1588                            if (!owner.equals(lock.getOwner())) {
1589                                    Date createDate = lock.getCreateDate();
1590    
1591                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1592                                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1593    
1594                                            // Acquire lock if the lock is older than the lock max time
1595    
1596                                            lock = LockLocalServiceUtil.lock(
1597                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1598                                                    String.valueOf(layout.getPlid()), lock.getOwner(),
1599                                                    owner);
1600    
1601                                            // Check if acquiring the lock succeeded or if another
1602                                            // process has the lock
1603    
1604                                            if (!owner.equals(lock.getOwner())) {
1605                                                    return;
1606                                            }
1607                                    }
1608                                    else {
1609                                            return;
1610                                    }
1611                            }
1612                    }
1613                    catch (Exception e) {
1614                            return;
1615                    }
1616    
1617                    try {
1618                            applyLayoutPrototype(layoutPrototype, layout, true);
1619                    }
1620                    catch (Exception e) {
1621                            _log.error(e, e);
1622    
1623                            prototypeTypeSettingsProperties.setProperty(
1624                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1625    
1626                            // Invoke updateImpl so that we do not trigger the listeners
1627    
1628                            LayoutUtil.updateImpl(layoutPrototypeLayout);
1629                    }
1630                    finally {
1631                            LockLocalServiceUtil.unlock(
1632                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1633                                    String.valueOf(layout.getPlid()), owner);
1634                    }
1635            }
1636    
1637            /**
1638             * Resets the modified timestamp on the layout, and then calls {@link
1639             * #doResetPrototype(LayoutSet)} to reset the modified timestamp on the
1640             * layout's site.
1641             *
1642             * <p>
1643             * After the timestamps are reset, the modified page template and site
1644             * template are merged into their linked layout and site when they are first
1645             * accessed.
1646             * </p>
1647             *
1648             * @param  layout the page having its timestamp reset
1649             * @throws PortalException if no site was associated with the layout or if a
1650             *         portal exception occurred
1651             * @throws SystemException if a system exception occurred
1652             */
1653            protected void doResetPrototype(Layout layout)
1654                    throws PortalException, SystemException {
1655    
1656                    layout.setModifiedDate(null);
1657    
1658                    LayoutLocalServiceUtil.updateLayout(layout);
1659    
1660                    LayoutSet layoutSet = layout.getLayoutSet();
1661    
1662                    doResetPrototype(layoutSet);
1663            }
1664    
1665            /**
1666             * Resets the modified timestamp on the layout set.
1667             *
1668             * <p>
1669             * After the timestamp is reset, the modified site template is merged into
1670             * its linked layout set when it is first accessed.
1671             * </p>
1672             *
1673             * @param  layoutSet the site having its timestamp reset
1674             * @throws SystemException if a system exception occurred
1675             */
1676            protected void doResetPrototype(LayoutSet layoutSet)
1677                    throws SystemException {
1678    
1679                    UnicodeProperties settingsProperties =
1680                            layoutSet.getSettingsProperties();
1681    
1682                    settingsProperties.remove(LAST_MERGE_TIME);
1683    
1684                    settingsProperties.setProperty(
1685                            LAST_RESET_TIME, String.valueOf(System.currentTimeMillis()));
1686    
1687                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
1688            }
1689    
1690            protected Map<String, String[]> getLayoutSetPrototypesParameters(
1691                    boolean importData) {
1692    
1693                    Map<String, String[]> parameterMap =
1694                            new LinkedHashMap<String, String[]>();
1695    
1696                    parameterMap.put(
1697                            PortletDataHandlerKeys.CATEGORIES,
1698                            new String[] {Boolean.TRUE.toString()});
1699                    parameterMap.put(
1700                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1701                            new String[] {Boolean.FALSE.toString()});
1702                    parameterMap.put(
1703                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1704                            new String[] {Boolean.FALSE.toString()});
1705                    parameterMap.put(
1706                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
1707                            new String[] {Boolean.TRUE.toString()});
1708                    parameterMap.put(
1709                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
1710                            new String[] {Boolean.TRUE.toString()});
1711                    parameterMap.put(
1712                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1713                            new String[] {Boolean.TRUE.toString()});
1714                    parameterMap.put(
1715                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
1716                            new String[] {
1717                                    PortletDataHandlerKeys.
1718                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
1719                            });
1720                    parameterMap.put(
1721                            PortletDataHandlerKeys.LOGO,
1722                            new String[] {Boolean.TRUE.toString()});
1723                    parameterMap.put(
1724                            PortletDataHandlerKeys.PERMISSIONS,
1725                            new String[] {Boolean.TRUE.toString()});
1726                    parameterMap.put(
1727                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
1728                            new String[] {Boolean.TRUE.toString()});
1729                    parameterMap.put(
1730                            PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL,
1731                            new String[] {Boolean.TRUE.toString()});
1732                    parameterMap.put(
1733                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
1734                            new String[] {Boolean.TRUE.toString()});
1735                    parameterMap.put(
1736                            PortletDataHandlerKeys.THEME_REFERENCE,
1737                            new String[] {Boolean.TRUE.toString()});
1738                    parameterMap.put(
1739                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1740                            new String[] {Boolean.FALSE.toString()});
1741                    parameterMap.put(
1742                            PortletDataHandlerKeys.USER_ID_STRATEGY,
1743                            new String[] {UserIdStrategy.CURRENT_USER_ID});
1744    
1745                    if (importData) {
1746                            parameterMap.put(
1747                                    PortletDataHandlerKeys.DATA_STRATEGY,
1748                                    new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
1749                            parameterMap.put(
1750                                    PortletDataHandlerKeys.PORTLET_DATA,
1751                                    new String[] {Boolean.TRUE.toString()});
1752                            parameterMap.put(
1753                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1754                                    new String[] {Boolean.TRUE.toString()});
1755                    }
1756                    else {
1757                            parameterMap.put(
1758                                    PortletDataHandlerKeys.PORTLET_DATA,
1759                                    new String[] {Boolean.FALSE.toString()});
1760                            parameterMap.put(
1761                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1762                                    new String[] {Boolean.FALSE.toString()});
1763                    }
1764    
1765                    return parameterMap;
1766            }
1767    
1768            protected void importLayoutSetPrototype(
1769                            LayoutSetPrototype layoutSetPrototype, long groupId,
1770                            boolean privateLayout, Map<String, String[]> parameterMap,
1771                            boolean importData)
1772                    throws PortalException, SystemException {
1773    
1774                    File file = null;
1775    
1776                    StringBundler sb = new StringBundler(importData ? 4 : 3);
1777    
1778                    sb.append(_TEMP_DIR);
1779                    sb.append(layoutSetPrototype.getUuid());
1780    
1781                    if (importData) {
1782                            sb.append("-data");
1783                    }
1784    
1785                    sb.append(".lar");
1786    
1787                    File cacheFile = new File(sb.toString());
1788    
1789                    if (cacheFile.exists()) {
1790                            Date modifiedDate = layoutSetPrototype.getModifiedDate();
1791    
1792                            if (cacheFile.lastModified() >= modifiedDate.getTime()) {
1793                                    if (_log.isDebugEnabled()) {
1794                                            _log.debug(
1795                                                    "Using cached layout set prototype LAR file " +
1796                                                            cacheFile.getAbsolutePath());
1797                                    }
1798    
1799                                    file = cacheFile;
1800                            }
1801                    }
1802    
1803                    boolean newFile = false;
1804    
1805                    if (file == null) {
1806                            file = LayoutLocalServiceUtil.exportLayoutsAsFile(
1807                                    layoutSetPrototype.getGroupId(), true, null, parameterMap, null,
1808                                    null);
1809    
1810                            newFile = true;
1811                    }
1812    
1813                    long userId = UserLocalServiceUtil.getDefaultUserId(
1814                            layoutSetPrototype.getCompanyId());
1815    
1816                    LayoutLocalServiceUtil.importLayouts(
1817                            userId, groupId, privateLayout, parameterMap, file);
1818    
1819                    if (newFile) {
1820                            try {
1821                                    FileUtil.copyFile(file, cacheFile);
1822    
1823                                    if (_log.isDebugEnabled()) {
1824                                            _log.debug(
1825                                                    "Copied " + file.getAbsolutePath() + " to " +
1826                                                            cacheFile.getAbsolutePath());
1827                                    }
1828                            }
1829                            catch (Exception e) {
1830                                    _log.error(
1831                                            "Unable to copy file " + file.getAbsolutePath() + " to " +
1832                                                    cacheFile.getAbsolutePath(),
1833                                            e);
1834                            }
1835                    }
1836            }
1837    
1838            protected void setLayoutSetPrototypeLinkEnabledParameter(
1839                    Map<String, String[]> parameterMap, LayoutSet targetLayoutSet,
1840                    ServiceContext serviceContext) {
1841    
1842                    PermissionChecker permissionChecker =
1843                            PermissionThreadLocal.getPermissionChecker();
1844    
1845                    if ((permissionChecker == null) ||
1846                            !PortalPermissionUtil.contains(
1847                                    permissionChecker, ActionKeys.UNLINK_LAYOUT_SET_PROTOTYPE)) {
1848    
1849                            return;
1850                    }
1851    
1852                    if (targetLayoutSet.isPrivateLayout()) {
1853                            boolean privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1854                                    serviceContext, "privateLayoutSetPrototypeLinkEnabled", true);
1855    
1856                            if (!privateLayoutSetPrototypeLinkEnabled) {
1857                                    privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1858                                            serviceContext, "layoutSetPrototypeLinkEnabled");
1859                            }
1860    
1861                            parameterMap.put(
1862                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1863                                    new String[] {
1864                                            String.valueOf(privateLayoutSetPrototypeLinkEnabled)
1865                                    });
1866                    }
1867                    else {
1868                            boolean publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1869                                    serviceContext, "publicLayoutSetPrototypeLinkEnabled");
1870    
1871                            if (!publicLayoutSetPrototypeLinkEnabled) {
1872                                    publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1873                                            serviceContext, "layoutSetPrototypeLinkEnabled", true);
1874                            }
1875    
1876                            parameterMap.put(
1877                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1878                                    new String[] {
1879                                            String.valueOf(publicLayoutSetPrototypeLinkEnabled)
1880                                    });
1881                    }
1882            }
1883    
1884            protected void updateLayoutSetPrototypeLink(
1885                            long groupId, boolean privateLayout, long layoutSetPrototypeId,
1886                            boolean layoutSetPrototypeLinkEnabled)
1887                    throws Exception {
1888    
1889                    String layoutSetPrototypeUuid = null;
1890    
1891                    if (layoutSetPrototypeId > 0) {
1892                            LayoutSetPrototype layoutSetPrototype =
1893                                    LayoutSetPrototypeLocalServiceUtil.fetchLayoutSetPrototype(
1894                                            layoutSetPrototypeId);
1895    
1896                            if (layoutSetPrototype != null) {
1897                                    layoutSetPrototypeUuid = layoutSetPrototype.getUuid();
1898    
1899                                    // Merge without enabling the link
1900    
1901                                    if (!layoutSetPrototypeLinkEnabled &&
1902                                            (layoutSetPrototypeId > 0)) {
1903    
1904                                            Map<String, String[]> parameterMap =
1905                                                    getLayoutSetPrototypesParameters(true);
1906    
1907                                            importLayoutSetPrototype(
1908                                                    layoutSetPrototype, groupId, privateLayout,
1909                                                    parameterMap, true);
1910                                    }
1911                            }
1912                    }
1913    
1914                    LayoutSetServiceUtil.updateLayoutSetPrototypeLinkEnabled(
1915                            groupId, privateLayout, layoutSetPrototypeLinkEnabled,
1916                            layoutSetPrototypeUuid);
1917    
1918                    LayoutLocalServiceUtil.updatePriorities(groupId, privateLayout);
1919            }
1920    
1921            private static final String _TEMP_DIR =
1922                    SystemProperties.get(SystemProperties.TMP_DIR) +
1923                            "/liferay/layout_set_prototype/";
1924    
1925            private static Log _log = LogFactoryUtil.getLog(SitesImpl.class);
1926    
1927    }