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