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