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