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