001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.sites.util;
016    
017    import com.liferay.portal.RequiredLayoutException;
018    import com.liferay.portal.events.EventsProcessorUtil;
019    import com.liferay.portal.kernel.dao.orm.QueryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024    import com.liferay.portal.kernel.lar.UserIdStrategy;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.ArrayUtil;
028    import com.liferay.portal.kernel.util.FileUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.OrderByComparator;
031    import com.liferay.portal.kernel.util.ParamUtil;
032    import com.liferay.portal.kernel.util.PrefsPropsUtil;
033    import com.liferay.portal.kernel.util.PropsKeys;
034    import com.liferay.portal.kernel.util.StringBundler;
035    import com.liferay.portal.kernel.util.SystemProperties;
036    import com.liferay.portal.kernel.util.UnicodeProperties;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
039    import com.liferay.portal.model.Group;
040    import com.liferay.portal.model.GroupConstants;
041    import com.liferay.portal.model.Layout;
042    import com.liferay.portal.model.LayoutConstants;
043    import com.liferay.portal.model.LayoutPrototype;
044    import com.liferay.portal.model.LayoutSet;
045    import com.liferay.portal.model.LayoutSetPrototype;
046    import com.liferay.portal.model.LayoutTypePortlet;
047    import com.liferay.portal.model.Lock;
048    import com.liferay.portal.model.Organization;
049    import com.liferay.portal.model.OrganizationConstants;
050    import com.liferay.portal.model.PortletConstants;
051    import com.liferay.portal.model.ResourceConstants;
052    import com.liferay.portal.model.Role;
053    import com.liferay.portal.model.RoleConstants;
054    import com.liferay.portal.model.User;
055    import com.liferay.portal.model.UserGroup;
056    import com.liferay.portal.model.impl.VirtualLayout;
057    import com.liferay.portal.security.auth.PrincipalException;
058    import com.liferay.portal.security.permission.ActionKeys;
059    import com.liferay.portal.security.permission.PermissionChecker;
060    import com.liferay.portal.security.permission.PermissionThreadLocal;
061    import com.liferay.portal.security.permission.ResourceActionsUtil;
062    import com.liferay.portal.service.GroupLocalServiceUtil;
063    import com.liferay.portal.service.GroupServiceUtil;
064    import com.liferay.portal.service.LayoutLocalServiceUtil;
065    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
066    import com.liferay.portal.service.LayoutServiceUtil;
067    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
068    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
069    import com.liferay.portal.service.LayoutSetServiceUtil;
070    import com.liferay.portal.service.LockLocalServiceUtil;
071    import com.liferay.portal.service.OrganizationLocalServiceUtil;
072    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
073    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
074    import com.liferay.portal.service.RoleLocalServiceUtil;
075    import com.liferay.portal.service.ServiceContext;
076    import com.liferay.portal.service.ServiceContextFactory;
077    import com.liferay.portal.service.ServiceContextThreadLocal;
078    import com.liferay.portal.service.UserGroupLocalServiceUtil;
079    import com.liferay.portal.service.UserLocalServiceUtil;
080    import com.liferay.portal.service.impl.LayoutLocalServiceVirtualLayoutsAdvice;
081    import com.liferay.portal.service.permission.GroupPermissionUtil;
082    import com.liferay.portal.service.permission.LayoutPermissionUtil;
083    import com.liferay.portal.service.permission.PortalPermissionUtil;
084    import com.liferay.portal.service.permission.PortletPermissionUtil;
085    import com.liferay.portal.service.persistence.LayoutSetUtil;
086    import com.liferay.portal.service.persistence.LayoutUtil;
087    import com.liferay.portal.theme.PortletDisplay;
088    import com.liferay.portal.theme.ThemeDisplay;
089    import com.liferay.portal.util.LayoutSettings;
090    import com.liferay.portal.util.PortalUtil;
091    import com.liferay.portal.util.PortletKeys;
092    import com.liferay.portal.util.PropsValues;
093    import com.liferay.portal.util.WebKeys;
094    import com.liferay.portlet.PortletPreferencesFactoryUtil;
095    import com.liferay.portlet.PortletPreferencesImpl;
096    
097    import java.io.File;
098    import java.io.InputStream;
099    
100    import java.util.ArrayList;
101    import java.util.Collections;
102    import java.util.Date;
103    import java.util.LinkedHashMap;
104    import java.util.List;
105    import java.util.Locale;
106    import java.util.Map;
107    
108    import javax.portlet.ActionRequest;
109    import javax.portlet.ActionResponse;
110    import javax.portlet.PortletPreferences;
111    import javax.portlet.PortletURL;
112    import javax.portlet.RenderRequest;
113    import javax.portlet.RenderResponse;
114    
115    import javax.servlet.http.HttpServletRequest;
116    import javax.servlet.http.HttpServletResponse;
117    
118    /**
119     * @author Raymond Augé
120     * @author Ryan Park
121     * @author Zsolt Berentey
122     */
123    public class SitesUtil {
124    
125            public static final String ANALYTICS_PREFIX = "analytics_";
126    
127            public static final int CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE = -1;
128    
129            public static final int CONTENT_SHARING_WITH_CHILDREN_DISABLED = 0;
130    
131            public static final int CONTENT_SHARING_WITH_CHILDREN_DISABLED_BY_DEFAULT =
132                    1;
133    
134            public static final int CONTENT_SHARING_WITH_CHILDREN_ENABLED = 3;
135    
136            public static final int CONTENT_SHARING_WITH_CHILDREN_ENABLED_BY_DEFAULT =
137                    2;
138    
139            public static final String LAST_MERGE_TIME = "last-merge-time";
140    
141            public static final String LAST_RESET_TIME = "last-reset-time";
142    
143            public static final String LAYOUT_UPDATEABLE = "layoutUpdateable";
144    
145            public static final String MERGE_FAIL_COUNT = "merge-fail-count";
146    
147            public static void addPortletBreadcrumbEntries(
148                            Group group, HttpServletRequest request,
149                            RenderResponse renderResponse)
150                    throws Exception {
151    
152                    PortletURL portletURL = renderResponse.createRenderURL();
153    
154                    portletURL.setParameter("struts_action", "/sites_admin/view");
155    
156                    List<Group> ancestorGroups = group.getAncestors();
157    
158                    Collections.reverse(ancestorGroups);
159    
160                    for (Group ancestorGroup : ancestorGroups) {
161                            portletURL.setParameter(
162                                    "groupId", String.valueOf(ancestorGroup.getGroupId()));
163    
164                            PortalUtil.addPortletBreadcrumbEntry(
165                                    request, ancestorGroup.getDescriptiveName(),
166                                    portletURL.toString());
167                    }
168    
169                    Group unescapedGroup = group.toUnescapedModel();
170    
171                    portletURL.setParameter(
172                            "groupId", String.valueOf(unescapedGroup.getGroupId()));
173    
174                    PortalUtil.addPortletBreadcrumbEntry(
175                            request, unescapedGroup.getDescriptiveName(),
176                            portletURL.toString());
177            }
178    
179            public static void addPortletBreadcrumbEntries(
180                            Group group, String pagesName, PortletURL redirectURL,
181                            HttpServletRequest request, RenderResponse renderResponse)
182                    throws Exception {
183    
184                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
185                            com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
186    
187                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
188    
189                    String portletName = portletDisplay.getPortletName();
190    
191                    if ((renderResponse == null) ||
192                            portletName.equals(PortletKeys.GROUP_PAGES) ||
193                            portletName.equals(PortletKeys.MY_PAGES)) {
194    
195                            return;
196                    }
197    
198                    Group unescapedGroup = group.toUnescapedModel();
199    
200                    Locale locale = themeDisplay.getLocale();
201    
202                    if (group.isLayoutPrototype()) {
203                            PortalUtil.addPortletBreadcrumbEntry(
204                                    request, LanguageUtil.get(locale, "page-template"), null);
205    
206                            PortalUtil.addPortletBreadcrumbEntry(
207                                    request, unescapedGroup.getDescriptiveName(),
208                                    redirectURL.toString());
209                    }
210                    else {
211                            PortalUtil.addPortletBreadcrumbEntry(
212                                    request, unescapedGroup.getDescriptiveName(), null);
213                    }
214    
215                    if (!group.isLayoutPrototype()) {
216                            PortalUtil.addPortletBreadcrumbEntry(
217                                    request, LanguageUtil.get(locale, pagesName),
218                                    redirectURL.toString());
219                    }
220            }
221    
222            public static void applyLayoutPrototype(
223                            LayoutPrototype layoutPrototype, Layout targetLayout,
224                            boolean linkEnabled)
225                    throws Exception {
226    
227                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
228    
229                    ServiceContext serviceContext =
230                            ServiceContextThreadLocal.getServiceContext();
231    
232                    serviceContext.setAttribute("layoutPrototypeLinkEnabled", linkEnabled);
233                    serviceContext.setAttribute(
234                            "layoutPrototypeUuid", layoutPrototype.getUuid());
235    
236                    targetLayout = LayoutLocalServiceUtil.updateLayout(
237                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
238                            targetLayout.getLayoutId(), targetLayout.getParentLayoutId(),
239                            targetLayout.getNameMap(), targetLayout.getTitleMap(),
240                            targetLayout.getDescriptionMap(), targetLayout.getKeywordsMap(),
241                            targetLayout.getRobotsMap(), layoutPrototypeLayout.getType(),
242                            targetLayout.getHidden(), targetLayout.getFriendlyURL(),
243                            targetLayout.getIconImage(), null, serviceContext);
244    
245                    targetLayout = LayoutLocalServiceUtil.updateLayout(
246                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
247                            targetLayout.getLayoutId(),
248                            layoutPrototypeLayout.getTypeSettings());
249    
250                    copyPortletPermissions(targetLayout, layoutPrototypeLayout);
251    
252                    copyPortletSetups(layoutPrototypeLayout, targetLayout);
253    
254                    copyLookAndFeel(targetLayout, layoutPrototypeLayout);
255    
256                    targetLayout = LayoutLocalServiceUtil.getLayout(targetLayout.getPlid());
257    
258                    UnicodeProperties typeSettingsProperties =
259                            targetLayout.getTypeSettingsProperties();
260    
261                    typeSettingsProperties.setProperty(
262                            LAST_MERGE_TIME,
263                            String.valueOf(targetLayout.getModifiedDate().getTime()));
264    
265                    LayoutLocalServiceUtil.updateLayout(targetLayout);
266    
267                    UnicodeProperties prototypeTypeSettingsProperties =
268                            layoutPrototypeLayout.getTypeSettingsProperties();
269    
270                    prototypeTypeSettingsProperties.setProperty(MERGE_FAIL_COUNT, "0");
271    
272                    LayoutLocalServiceUtil.updateLayout(layoutPrototypeLayout);
273            }
274    
275            public static void copyLayout(
276                            long userId, Layout sourceLayout, Layout targetLayout,
277                            ServiceContext serviceContext)
278                    throws Exception {
279    
280                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
281                            serviceContext);
282    
283                    parameterMap.put(
284                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
285                            new String[] {Boolean.FALSE.toString()});
286    
287                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
288                            sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
289                            new long[] {sourceLayout.getLayoutId()}, parameterMap, null, null);
290    
291                    try {
292                            LayoutLocalServiceUtil.importLayouts(
293                                    userId, targetLayout.getGroupId(),
294                                    targetLayout.isPrivateLayout(), parameterMap, file);
295                    }
296                    finally {
297                            file.delete();
298                    }
299            }
300    
301            public static void copyLookAndFeel(Layout targetLayout, Layout sourceLayout)
302                    throws Exception {
303    
304                    LayoutLocalServiceUtil.updateLookAndFeel(
305                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
306                            targetLayout.getLayoutId(), sourceLayout.getThemeId(),
307                            sourceLayout.getColorSchemeId(), sourceLayout.getCss(), false);
308    
309                    LayoutLocalServiceUtil.updateLookAndFeel(
310                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
311                            targetLayout.getLayoutId(), sourceLayout.getWapThemeId(),
312                            sourceLayout.getWapColorSchemeId(), sourceLayout.getCss(), true);
313            }
314    
315            public static void copyPortletPermissions(
316                            Layout targetLayout, Layout sourceLayout)
317                    throws Exception {
318    
319                    long companyId = targetLayout.getCompanyId();
320    
321                    List<Role> roles = RoleLocalServiceUtil.getRoles(companyId);
322    
323                    LayoutTypePortlet sourceLayoutTypePortlet =
324                            (LayoutTypePortlet)sourceLayout.getLayoutType();
325    
326                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
327    
328                    for (String sourcePortletId : sourcePortletIds) {
329                            String resourceName = PortletConstants.getRootPortletId(
330                                    sourcePortletId);
331    
332                            String sourceResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
333                                    sourceLayout.getPlid(), sourcePortletId);
334    
335                            String targetResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
336                                    targetLayout.getPlid(), sourcePortletId);
337    
338                            List<String> actionIds =
339                                    ResourceActionsUtil.getPortletResourceActions(resourceName);
340    
341                            for (Role role : roles) {
342                                    String roleName = role.getName();
343    
344                                    if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
345                                            continue;
346                                    }
347    
348                                    List<String> actions =
349                                            ResourcePermissionLocalServiceUtil.
350                                                    getAvailableResourcePermissionActionIds(
351                                                            companyId, resourceName,
352                                                            ResourceConstants.SCOPE_INDIVIDUAL,
353                                                            sourceResourcePrimKey, role.getRoleId(), actionIds);
354    
355                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
356                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
357                                            targetResourcePrimKey, role.getRoleId(),
358                                            actions.toArray(new String[actions.size()]));
359                            }
360                    }
361            }
362    
363            public static void copyPortletSetups(
364                            Layout sourceLayout, Layout targetLayout)
365                    throws Exception {
366    
367                    LayoutTypePortlet sourceLayoutTypePortlet =
368                            (LayoutTypePortlet)sourceLayout.getLayoutType();
369    
370                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
371    
372                    for (String sourcePortletId : sourcePortletIds) {
373                            PortletPreferences sourcePreferences =
374                                    PortletPreferencesFactoryUtil.getPortletSetup(
375                                            sourceLayout, sourcePortletId, null);
376    
377                            PortletPreferencesImpl sourcePreferencesImpl =
378                                    (PortletPreferencesImpl)sourcePreferences;
379    
380                            PortletPreferences targetPreferences =
381                                    PortletPreferencesFactoryUtil.getPortletSetup(
382                                            targetLayout, sourcePortletId, null);
383    
384                            PortletPreferencesImpl targetPreferencesImpl =
385                                    (PortletPreferencesImpl)targetPreferences;
386    
387                            PortletPreferencesLocalServiceUtil.updatePreferences(
388                                    targetPreferencesImpl.getOwnerId(),
389                                    targetPreferencesImpl.getOwnerType(),
390                                    targetPreferencesImpl.getPlid(), sourcePortletId,
391                                    sourcePreferences);
392    
393                            if ((sourcePreferencesImpl.getOwnerId() !=
394                                            PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
395                                    (sourcePreferencesImpl.getOwnerType() !=
396                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) {
397    
398                                    sourcePreferences =
399                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
400                                                    sourceLayout, sourcePortletId);
401    
402                                    sourcePreferencesImpl =
403                                            (PortletPreferencesImpl)sourcePreferences;
404    
405                                    targetPreferences =
406                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
407                                                    targetLayout, sourcePortletId);
408    
409                                    targetPreferencesImpl =
410                                            (PortletPreferencesImpl)targetPreferences;
411    
412                                    PortletPreferencesLocalServiceUtil.updatePreferences(
413                                            targetPreferencesImpl.getOwnerId(),
414                                            targetPreferencesImpl.getOwnerType(),
415                                            targetPreferencesImpl.getPlid(), sourcePortletId,
416                                            sourcePreferences);
417                            }
418    
419                            ServiceContext serviceContext =
420                                    ServiceContextThreadLocal.getServiceContext();
421    
422                            updateLayoutScopes(
423                                    serviceContext.getUserId(), sourceLayout, targetLayout,
424                                    sourcePreferences, targetPreferences, sourcePortletId,
425                                    serviceContext.getLanguageId());
426                    }
427            }
428    
429            public static void copyTypeSettings(Group sourceGroup, Group targetGroup)
430                    throws Exception {
431    
432                    GroupServiceUtil.updateGroup(
433                            targetGroup.getGroupId(), sourceGroup.getTypeSettings());
434            }
435    
436            public static Object[] deleteLayout(
437                            ActionRequest actionRequest, ActionResponse actionResponse)
438                    throws Exception {
439    
440                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
441                            actionRequest);
442                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
443                            actionResponse);
444    
445                    return deleteLayout(request, response);
446            }
447    
448            public static Object[] deleteLayout(
449                            HttpServletRequest request, HttpServletResponse response)
450                    throws Exception {
451    
452                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
453                            WebKeys.THEME_DISPLAY);
454    
455                    PermissionChecker permissionChecker =
456                            themeDisplay.getPermissionChecker();
457    
458                    long plid = ParamUtil.getLong(request, "plid");
459    
460                    long groupId = ParamUtil.getLong(request, "groupId");
461                    boolean privateLayout = ParamUtil.getBoolean(request, "privateLayout");
462                    long layoutId = ParamUtil.getLong(request, "layoutId");
463    
464                    Layout layout = null;
465    
466                    if (plid <= 0) {
467                            layout = LayoutLocalServiceUtil.getLayout(
468                                    groupId, privateLayout, layoutId);
469                    }
470                    else {
471                            layout = LayoutLocalServiceUtil.getLayout(plid);
472    
473                            groupId = layout.getGroupId();
474                            privateLayout = layout.isPrivateLayout();
475                            layoutId = layout.getLayoutId();
476                    }
477    
478                    Group group = layout.getGroup();
479                    String oldFriendlyURL = layout.getFriendlyURL();
480    
481                    if (group.isStagingGroup() &&
482                            !GroupPermissionUtil.contains(
483                                    permissionChecker, groupId, ActionKeys.MANAGE_STAGING) &&
484                            !GroupPermissionUtil.contains(
485                                    permissionChecker, groupId, ActionKeys.PUBLISH_STAGING)) {
486    
487                            throw new PrincipalException();
488                    }
489    
490                    if (LayoutPermissionUtil.contains(
491                                    permissionChecker, layout, ActionKeys.DELETE)) {
492    
493                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
494    
495                            EventsProcessorUtil.process(
496                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_DELETE,
497                                    layoutSettings.getConfigurationActionDelete(), request,
498                                    response);
499                    }
500    
501                    LayoutSet layoutSet = layout.getLayoutSet();
502    
503                    if (group.isGuest() && (layoutSet.getPageCount() == 1)) {
504                            throw new RequiredLayoutException(
505                                    RequiredLayoutException.AT_LEAST_ONE);
506                    }
507    
508                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
509                            request);
510    
511                    LayoutServiceUtil.deleteLayout(
512                            groupId, privateLayout, layoutId, serviceContext);
513    
514                    long newPlid = layout.getParentPlid();
515    
516                    if (newPlid <= 0) {
517                            Layout firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
518                                    layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
519                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
520    
521                            if (firstLayout != null) {
522                                    newPlid = firstLayout.getPlid();
523                            }
524                    }
525    
526                    return new Object[] {group, oldFriendlyURL, newPlid};
527            }
528    
529            public static void deleteLayout(
530                            RenderRequest renderRequest, RenderResponse renderResponse)
531                    throws Exception {
532    
533                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
534                            renderRequest);
535                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
536                            renderResponse);
537    
538                    deleteLayout(request, response);
539            }
540    
541            public static File exportLayoutSetPrototype(
542                            LayoutSetPrototype layoutSetPrototype,
543                            ServiceContext serviceContext)
544                    throws PortalException, SystemException {
545    
546                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
547    
548                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
549                            serviceContext);
550    
551                    return LayoutLocalServiceUtil.exportLayoutsAsFile(
552                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), null,
553                            parameterMap, null, null);
554            }
555    
556            public static Long[] filterGroups(List<Group> groups, String[] names) {
557                    List<Long> groupIds = new ArrayList<Long>();
558    
559                    for (Group group : groups) {
560                            if (!ArrayUtil.contains(names, group.getName())) {
561                                    groupIds.add(group.getGroupId());
562                            }
563                    }
564    
565                    return ArrayUtil.toArray(ArrayUtil.toLongArray(groupIds));
566            }
567    
568            public static Layout getLayoutSetPrototypeLayout(Layout layout) {
569                    try {
570                            LayoutSet layoutSet = layout.getLayoutSet();
571    
572                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
573                                    return null;
574                            }
575    
576                            LayoutSetPrototype layoutSetPrototype =
577                                    LayoutSetPrototypeLocalServiceUtil.
578                                            getLayoutSetPrototypeByUuidAndCompanyId(
579                                                    layoutSet.getLayoutSetPrototypeUuid(),
580                                                    layout.getCompanyId());
581    
582                            Group group = layoutSetPrototype.getGroup();
583    
584                            return LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
585                                    layout.getSourcePrototypeLayoutUuid(), group.getGroupId(),
586                                    true);
587                    }
588                    catch (Exception e) {
589                            _log.error(
590                                    "Unable to fetch the the layout set prototype's layout", e);
591                    }
592    
593                    return null;
594            }
595    
596            public static Map<String, String[]> getLayoutSetPrototypeParameters(
597                    ServiceContext serviceContext) {
598    
599                    Map<String, String[]> parameterMap =
600                            new LinkedHashMap<String, String[]>();
601    
602                    parameterMap.put(
603                            PortletDataHandlerKeys.CATEGORIES,
604                            new String[] {Boolean.TRUE.toString()});
605                    parameterMap.put(
606                            PortletDataHandlerKeys.DATA_STRATEGY,
607                            new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
608                    parameterMap.put(
609                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
610                            new String[] {Boolean.TRUE.toString()});
611                    parameterMap.put(
612                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
613                            new String[] {Boolean.FALSE.toString()});
614                    parameterMap.put(
615                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
616                            new String[] {Boolean.TRUE.toString()});
617                    parameterMap.put(
618                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
619                            new String[] {Boolean.TRUE.toString()});
620                    parameterMap.put(
621                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
622                            new String[] {
623                                    PortletDataHandlerKeys.
624                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
625                            });
626                    parameterMap.put(
627                            PortletDataHandlerKeys.LOGO,
628                            new String[] {Boolean.TRUE.toString()});
629                    parameterMap.put(
630                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
631                            new String[] {Boolean.TRUE.toString()});
632                    parameterMap.put(
633                            PortletDataHandlerKeys.PERMISSIONS,
634                            new String[] {Boolean.TRUE.toString()});
635                    parameterMap.put(
636                            PortletDataHandlerKeys.PORTLET_DATA,
637                            new String[] {Boolean.TRUE.toString()});
638                    parameterMap.put(
639                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
640                            new String[] {Boolean.TRUE.toString()});
641                    parameterMap.put(
642                            PortletDataHandlerKeys.PORTLET_SETUP,
643                            new String[] {Boolean.TRUE.toString()});
644                    parameterMap.put(
645                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
646                            new String[] {Boolean.TRUE.toString()});
647                    parameterMap.put(
648                            PortletDataHandlerKeys.THEME,
649                            new String[] {Boolean.FALSE.toString()});
650                    parameterMap.put(
651                            PortletDataHandlerKeys.THEME_REFERENCE,
652                            new String[] {Boolean.TRUE.toString()});
653                    parameterMap.put(
654                            PortletDataHandlerKeys.USER_ID_STRATEGY,
655                            new String[] {UserIdStrategy.CURRENT_USER_ID});
656    
657                    return parameterMap;
658            }
659    
660            public static void importLayoutSetPrototype(
661                            LayoutSetPrototype layoutSetPrototype, InputStream inputStream,
662                            ServiceContext serviceContext)
663                    throws PortalException, SystemException {
664    
665                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
666    
667                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
668                            serviceContext);
669    
670                    setLayoutSetPrototypeLinkEnabledParameter(
671                            parameterMap, layoutSet, serviceContext);
672    
673                    LayoutServiceUtil.importLayouts(
674                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), parameterMap,
675                            inputStream);
676            }
677    
678            public static boolean isContentSharingWithChildrenEnabled(Group group)
679                    throws SystemException {
680    
681                    UnicodeProperties typeSettingsProperties =
682                            group.getParentLiveGroupTypeSettingsProperties();
683    
684                    int companyContentSharingEnabled = PrefsPropsUtil.getInteger(
685                            group.getCompanyId(),
686                            PropsKeys.SITES_CONTENT_SHARING_WITH_CHILDREN_ENABLED);
687    
688                    if (companyContentSharingEnabled ==
689                                    SitesUtil.CONTENT_SHARING_WITH_CHILDREN_DISABLED) {
690    
691                            return false;
692                    }
693    
694                    int groupContentSharingEnabled = GetterUtil.getInteger(
695                            typeSettingsProperties.getProperty(
696                                    "contentSharingWithChildrenEnabled"),
697                                    SitesUtil.CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE);
698    
699                    if ((groupContentSharingEnabled ==
700                                    SitesUtil.CONTENT_SHARING_WITH_CHILDREN_ENABLED) ||
701                            ((companyContentSharingEnabled ==
702                                    SitesUtil.CONTENT_SHARING_WITH_CHILDREN_ENABLED_BY_DEFAULT) &&
703                             (groupContentSharingEnabled ==
704                                    SitesUtil.CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE))) {
705    
706                            return true;
707                    }
708    
709                    return false;
710            }
711    
712            public static boolean isLayoutDeleteable(Layout layout) {
713                    try {
714                            if (layout instanceof VirtualLayout) {
715                                    return false;
716                            }
717    
718                            if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
719                                    return true;
720                            }
721    
722                            LayoutSet layoutSet = layout.getLayoutSet();
723    
724                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
725                                    return true;
726                            }
727    
728                            if (LayoutLocalServiceUtil.hasLayoutSetPrototypeLayout(
729                                            layoutSet.getLayoutSetPrototypeUuid(),
730                                            layout.getCompanyId(),
731                                            layout.getSourcePrototypeLayoutUuid())) {
732    
733                                    return false;
734                            }
735                    }
736                    catch (Exception e) {
737                            if (_log.isDebugEnabled()) {
738                                    _log.debug(e, e);
739                            }
740                    }
741    
742                    return true;
743            }
744    
745            public static boolean isLayoutModifiedSinceLastMerge(Layout layout) {
746                    if ((layout == null) ||
747                            Validator.isNull(layout.getSourcePrototypeLayoutUuid()) ||
748                            layout.isLayoutPrototypeLinkActive() ||
749                            !isLayoutUpdateable(layout)) {
750    
751                            return false;
752                    }
753    
754                    long lastMergeTime = GetterUtil.getLong(
755                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
756    
757                    Date existingLayoutModifiedDate = layout.getModifiedDate();
758    
759                    if ((existingLayoutModifiedDate != null) &&
760                            (existingLayoutModifiedDate.getTime() > lastMergeTime)) {
761    
762                            return true;
763                    }
764    
765                    return false;
766            }
767    
768            public static boolean isLayoutSetPrototypeUpdateable(LayoutSet layoutSet) {
769                    if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
770                            return true;
771                    }
772    
773                    try {
774                            LayoutSetPrototype layoutSetPrototype =
775                                    LayoutSetPrototypeLocalServiceUtil.
776                                            getLayoutSetPrototypeByUuidAndCompanyId(
777                                                    layoutSet.getLayoutSetPrototypeUuid(),
778                                                    layoutSet.getCompanyId());
779    
780                            String layoutsUpdateable = layoutSetPrototype.getSettingsProperty(
781                                    "layoutsUpdateable");
782    
783                            if (Validator.isNotNull(layoutsUpdateable)) {
784                                    return GetterUtil.getBoolean(layoutsUpdateable, true);
785                            }
786                    }
787                    catch (Exception e) {
788                            if (_log.isDebugEnabled()) {
789                                    _log.debug(e, e);
790                            }
791                    }
792    
793                    return true;
794            }
795    
796            public static boolean isLayoutUpdateable(Layout layout) {
797                    try {
798                            if (layout instanceof VirtualLayout) {
799                                    return false;
800                            }
801    
802                            if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
803                                    Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
804    
805                                    return true;
806                            }
807    
808                            LayoutSet layoutSet = layout.getLayoutSet();
809    
810                            if (layoutSet.isLayoutSetPrototypeLinkActive()) {
811                                    boolean layoutSetPrototypeUpdateable =
812                                            isLayoutSetPrototypeUpdateable(layoutSet);
813    
814                                    if (!layoutSetPrototypeUpdateable) {
815                                            return false;
816                                    }
817    
818                                    Layout layoutSetPrototypeLayout = getLayoutSetPrototypeLayout(
819                                            layout);
820    
821                                    String layoutUpdateable =
822                                            layoutSetPrototypeLayout.getTypeSettingsProperty(
823                                                    LAYOUT_UPDATEABLE);
824    
825                                    if (Validator.isNull(layoutUpdateable)) {
826                                            return true;
827                                    }
828    
829                                    return GetterUtil.getBoolean(layoutUpdateable);
830                            }
831                    }
832                    catch (Exception e) {
833                            if (_log.isDebugEnabled()) {
834                                    _log.debug(e, e);
835                            }
836                    }
837    
838                    return true;
839            }
840    
841            public static boolean isOrganizationUser(
842                            long companyId, Group group, User user,
843                            List<String> organizationNames)
844                    throws Exception {
845    
846                    boolean organizationUser = false;
847    
848                    LinkedHashMap<String, Object> organizationParams =
849                            new LinkedHashMap<String, Object>();
850    
851                    organizationParams.put(
852                            "groupOrganization", new Long(group.getGroupId()));
853                    organizationParams.put(
854                            "organizationsGroups", new Long(group.getGroupId()));
855    
856                    List<Organization> organizationsGroups =
857                            OrganizationLocalServiceUtil.search(
858                                    companyId, OrganizationConstants.ANY_PARENT_ORGANIZATION_ID,
859                                    null, null, null, null, organizationParams, QueryUtil.ALL_POS,
860                                    QueryUtil.ALL_POS);
861    
862                    for (Organization organization : organizationsGroups) {
863                            for (long userOrganizationId : user.getOrganizationIds()) {
864                                    if (userOrganizationId == organization.getOrganizationId()) {
865                                            organizationNames.add(organization.getName());
866    
867                                            organizationUser = true;
868                                    }
869                            }
870                    }
871    
872                    return organizationUser;
873            }
874    
875            public static boolean isUserGroupLayoutSetViewable(
876                            PermissionChecker permissionChecker, Group userGroupGroup)
877                    throws PortalException, SystemException {
878    
879                    if (!userGroupGroup.isUserGroup()) {
880                            return false;
881                    }
882    
883                    if (GroupPermissionUtil.contains(
884                                    permissionChecker, userGroupGroup.getGroupId(),
885                                    ActionKeys.VIEW)) {
886    
887                            return true;
888                    }
889    
890                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
891                            userGroupGroup.getClassPK());
892    
893                    if (UserLocalServiceUtil.hasUserGroupUser(
894                                    userGroup.getUserGroupId(), permissionChecker.getUserId())) {
895    
896                            return true;
897                    }
898                    else {
899                            return false;
900                    }
901            }
902    
903            public static boolean isUserGroupUser(
904                            long companyId, Group group, User user, List<String> userGroupNames)
905                    throws Exception {
906    
907                    boolean userGroupUser = false;
908    
909                    LinkedHashMap<String, Object> userGroupParams =
910                            new LinkedHashMap<String, Object>();
911    
912                    userGroupParams.put("userGroupsGroups", new Long(group.getGroupId()));
913    
914                    List<UserGroup> userGroupsGroups = UserGroupLocalServiceUtil.search(
915                            companyId, null, userGroupParams, QueryUtil.ALL_POS,
916                            QueryUtil.ALL_POS, (OrderByComparator)null);
917    
918                    for (UserGroup userGroup : userGroupsGroups) {
919                            for (long userGroupId : user.getUserGroupIds()) {
920                                    if (userGroupId == userGroup.getUserGroupId()) {
921                                            userGroupNames.add(userGroup.getName());
922    
923                                            userGroupUser = true;
924                                    }
925                            }
926                    }
927    
928                    return userGroupUser;
929            }
930    
931            public static void mergeLayoutPrototypeLayout(Group group, Layout layout)
932                    throws Exception {
933    
934                    String sourcePrototypeLayoutUuid =
935                            layout.getSourcePrototypeLayoutUuid();
936    
937                    if (Validator.isNotNull(sourcePrototypeLayoutUuid)) {
938                            LayoutSet layoutSet = layout.getLayoutSet();
939    
940                            Group layoutSetPrototypeGroup =
941                                    GroupLocalServiceUtil.getLayoutSetPrototypeGroup(
942                                            layout.getCompanyId(), layoutSet.getLayoutSetPrototypeId());
943    
944                            Layout sourcePrototypeLayout =
945                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
946                                            sourcePrototypeLayoutUuid,
947                                            layoutSetPrototypeGroup.getGroupId(), true);
948    
949                            doMergeLayoutPrototypeLayout(
950                                    layoutSetPrototypeGroup, sourcePrototypeLayout);
951                    }
952    
953                    doMergeLayoutPrototypeLayout(group, layout);
954            }
955    
956            /**
957             * @deprecated {@link #mergeLayoutPrototypeLayout(Group, Layout)}
958             */
959            public static void mergeLayoutProtypeLayout(Group group, Layout layout)
960                    throws Exception {
961    
962                    mergeLayoutPrototypeLayout(group, layout);
963            }
964    
965            public static void mergeLayoutSetPrototypeLayouts(
966                            Group group, LayoutSet layoutSet)
967                    throws Exception {
968    
969                    if (!layoutSet.isLayoutSetPrototypeLinkActive() ||
970                            group.isLayoutPrototype() || group.isLayoutSetPrototype()) {
971    
972                            return;
973                    }
974    
975                    UnicodeProperties settingsProperties =
976                            layoutSet.getSettingsProperties();
977    
978                    long lastMergeTime = GetterUtil.getLong(
979                            settingsProperties.getProperty(LAST_MERGE_TIME));
980    
981                    LayoutSetPrototype layoutSetPrototype =
982                            LayoutSetPrototypeLocalServiceUtil.
983                                    getLayoutSetPrototypeByUuidAndCompanyId(
984                                            layoutSet.getLayoutSetPrototypeUuid(),
985                                            layoutSet.getCompanyId());
986    
987                    Date modifiedDate = layoutSetPrototype.getModifiedDate();
988    
989                    if (lastMergeTime >= modifiedDate.getTime()) {
990                            return;
991                    }
992    
993                    LayoutSet layoutSetPrototypeLayoutSet =
994                            layoutSetPrototype.getLayoutSet();
995    
996                    UnicodeProperties layoutSetPrototypeSettingsProperties =
997                            layoutSetPrototypeLayoutSet.getSettingsProperties();
998    
999                    int mergeFailCount = GetterUtil.getInteger(
1000                            layoutSetPrototypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1001    
1002                    if (mergeFailCount >
1003                            PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
1004    
1005                            if (_log.isWarnEnabled()) {
1006                                    StringBundler sb = new StringBundler(6);
1007    
1008                                    sb.append("Merge not performed because the fail threshold ");
1009                                    sb.append("was reached for layoutSetPrototypeId ");
1010                                    sb.append(layoutSetPrototype.getLayoutSetPrototypeId());
1011                                    sb.append(" and layoutId ");
1012                                    sb.append(layoutSetPrototypeLayoutSet.getLayoutSetId());
1013                                    sb.append(". Update the count in the database to try again.");
1014    
1015                                    _log.warn(sb.toString());
1016                            }
1017    
1018                            return;
1019                    }
1020    
1021                    String owner = PortalUUIDUtil.generate();
1022    
1023                    try {
1024                            Lock lock = LockLocalServiceUtil.lock(
1025                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1026                                    String.valueOf(layoutSet.getLayoutSetId()), owner, false);
1027    
1028                            // Double deep check
1029    
1030                            if (!owner.equals(lock.getOwner())) {
1031                                    Date createDate = lock.getCreateDate();
1032    
1033                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1034                                            PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1035    
1036                                            // Acquire lock if the lock is older than the lock max time
1037    
1038                                            lock = LockLocalServiceUtil.lock(
1039                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1040                                                    String.valueOf(layoutSet.getLayoutSetId()),
1041                                                    lock.getOwner(), owner, false);
1042    
1043                                            // Check if acquiring the lock succeeded or if another
1044                                            // process has the lock
1045    
1046                                            if (!owner.equals(lock.getOwner())) {
1047                                                    return;
1048                                            }
1049                                    }
1050                                    else {
1051                                            return;
1052                                    }
1053                            }
1054                    }
1055                    catch (Exception e) {
1056                            return;
1057                    }
1058    
1059                    try {
1060                            boolean importData = true;
1061    
1062                            long lastResetTime = GetterUtil.getLong(
1063                                    settingsProperties.getProperty(LAST_RESET_TIME));
1064    
1065                            if ((lastMergeTime > 0) || (lastResetTime > 0)) {
1066                                    importData = false;
1067                            }
1068    
1069                            Map<String, String[]> parameterMap =
1070                                    getLayoutSetPrototypesParameters(importData);
1071    
1072                            importLayoutSetPrototype(
1073                                    layoutSetPrototype, layoutSet.getGroupId(),
1074                                    layoutSet.isPrivateLayout(), parameterMap, importData);
1075                    }
1076                    catch (Exception e) {
1077                            _log.error(e, e);
1078    
1079                            layoutSetPrototypeSettingsProperties.setProperty(
1080                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1081    
1082                            // Invoke updateImpl so that we do not trigger the listeners
1083    
1084                            LayoutSetUtil.updateImpl(layoutSetPrototypeLayoutSet);
1085                    }
1086                    finally {
1087                            LockLocalServiceUtil.unlock(
1088                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1089                                    String.valueOf(layoutSet.getLayoutSetId()), owner, false);
1090                    }
1091            }
1092    
1093            /**
1094             * @deprecated {@link #mergeLayoutSetPrototypeLayouts(Group, LayoutSet)}
1095             */
1096            public static void mergeLayoutSetProtypeLayouts(
1097                            Group group, LayoutSet layoutSet)
1098                    throws Exception {
1099    
1100                    mergeLayoutSetPrototypeLayouts(group, layoutSet);
1101            }
1102    
1103            public static void resetPrototype(Layout layout)
1104                    throws PortalException, SystemException {
1105    
1106                    layout.setModifiedDate(null);
1107    
1108                    LayoutLocalServiceUtil.updateLayout(layout);
1109    
1110                    LayoutSet layoutSet = layout.getLayoutSet();
1111                    UnicodeProperties settingsProperties =
1112                            layoutSet.getSettingsProperties();
1113    
1114                    settingsProperties.remove(LAST_MERGE_TIME);
1115    
1116                    settingsProperties.setProperty(
1117                            LAST_RESET_TIME, String.valueOf(System.currentTimeMillis()));
1118    
1119                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
1120            }
1121    
1122            public static void updateLayoutScopes(
1123                            long userId, Layout sourceLayout, Layout targetLayout,
1124                            PortletPreferences sourcePreferences,
1125                            PortletPreferences targetPreferences, String sourcePortletId,
1126                            String languageId)
1127                    throws Exception {
1128    
1129                    String scopeType = GetterUtil.getString(
1130                            sourcePreferences.getValue("lfrScopeType", null));
1131    
1132                    if (Validator.isNull(scopeType) || !scopeType.equals("layout")) {
1133                            return;
1134                    }
1135    
1136                    Layout targetScopeLayout =
1137                            LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1138                                    targetLayout.getUuid(), targetLayout.getGroupId(),
1139                                    targetLayout.isPrivateLayout());
1140    
1141                    if (!targetScopeLayout.hasScopeGroup()) {
1142                            GroupLocalServiceUtil.addGroup(
1143                                    userId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
1144                                    Layout.class.getName(), targetLayout.getPlid(),
1145                                    GroupConstants.DEFAULT_LIVE_GROUP_ID,
1146                                    targetLayout.getName(languageId), null, 0, null, false, true,
1147                                    null);
1148                    }
1149    
1150                    String portletTitle = PortalUtil.getPortletTitle(
1151                            sourcePortletId, languageId);
1152    
1153                    String newPortletTitle = PortalUtil.getNewPortletTitle(
1154                            portletTitle, String.valueOf(sourceLayout.getLayoutId()),
1155                            targetLayout.getName(languageId));
1156    
1157                    targetPreferences.setValue(
1158                            "groupId", String.valueOf(targetLayout.getGroupId()));
1159                    targetPreferences.setValue("lfrScopeType", "layout");
1160                    targetPreferences.setValue(
1161                            "lfrScopeLayoutUuid", targetLayout.getUuid());
1162                    targetPreferences.setValue(
1163                            "portletSetupTitle_" + languageId, newPortletTitle);
1164                    targetPreferences.setValue(
1165                            "portletSetupUseCustomTitle", Boolean.TRUE.toString());
1166    
1167                    targetPreferences.store();
1168            }
1169    
1170            public static void updateLayoutSetPrototypesLinks(
1171                            Group group, long publicLayoutSetPrototypeId,
1172                            long privateLayoutSetPrototypeId,
1173                            boolean publicLayoutSetPrototypeLinkEnabled,
1174                            boolean privateLayoutSetPrototypeLinkEnabled)
1175                    throws Exception {
1176    
1177                    updateLayoutSetPrototypeLink(
1178                            group.getGroupId(), true, privateLayoutSetPrototypeId,
1179                            privateLayoutSetPrototypeLinkEnabled);
1180                    updateLayoutSetPrototypeLink(
1181                            group.getGroupId(), false, publicLayoutSetPrototypeId,
1182                            publicLayoutSetPrototypeLinkEnabled);
1183            }
1184    
1185            protected static void doMergeLayoutPrototypeLayout(
1186                            Group group, Layout layout)
1187                    throws Exception {
1188    
1189                    if (!layout.isLayoutPrototypeLinkActive() ||
1190                            group.isLayoutPrototype() || group.hasStagingGroup()) {
1191    
1192                            return;
1193                    }
1194    
1195                    long lastMergeTime = GetterUtil.getLong(
1196                            layout.getTypeSettingsProperty(LAST_MERGE_TIME));
1197    
1198                    LayoutPrototype layoutPrototype =
1199                            LayoutPrototypeLocalServiceUtil.
1200                                    getLayoutPrototypeByUuidAndCompanyId(
1201                                            layout.getLayoutPrototypeUuid(), layout.getCompanyId());
1202    
1203                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
1204    
1205                    Date modifiedDate = layoutPrototypeLayout.getModifiedDate();
1206    
1207                    if (lastMergeTime >= modifiedDate.getTime()) {
1208                            return;
1209                    }
1210    
1211                    UnicodeProperties prototypeTypeSettingsProperties =
1212                            layoutPrototypeLayout.getTypeSettingsProperties();
1213    
1214                    int mergeFailCount = GetterUtil.getInteger(
1215                            prototypeTypeSettingsProperties.getProperty(MERGE_FAIL_COUNT));
1216    
1217                    if (mergeFailCount >
1218                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
1219    
1220                            if (_log.isWarnEnabled()) {
1221                                    StringBundler sb = new StringBundler(6);
1222    
1223                                    sb.append("Merge not performed because the fail threshold ");
1224                                    sb.append("was reached for layoutPrototypeId ");
1225                                    sb.append(layoutPrototype.getLayoutPrototypeId());
1226                                    sb.append(" and layoutId ");
1227                                    sb.append(layoutPrototypeLayout.getLayoutId());
1228                                    sb.append(". Update the count in the database to try again.");
1229    
1230                                    _log.warn(sb.toString());
1231                            }
1232    
1233                            return;
1234                    }
1235    
1236                    String owner = PortalUUIDUtil.generate();
1237    
1238                    try {
1239                            Lock lock = LockLocalServiceUtil.lock(
1240                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1241                                    String.valueOf(layout.getPlid()), owner, false);
1242    
1243                            if (!owner.equals(lock.getOwner())) {
1244                                    Date createDate = lock.getCreateDate();
1245    
1246                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
1247                                                    PropsValues.LAYOUT_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
1248    
1249                                            // Acquire lock if the lock is older than the lock max time
1250    
1251                                            lock = LockLocalServiceUtil.lock(
1252                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1253                                                    String.valueOf(layout.getPlid()), lock.getOwner(),
1254                                                    owner, false);
1255    
1256                                            // Check if acquiring the lock succeeded or if another
1257                                            // process has the lock
1258    
1259                                            if (!owner.equals(lock.getOwner())) {
1260                                                    return;
1261                                            }
1262                                    }
1263                                    else {
1264                                            return;
1265                                    }
1266                            }
1267                    }
1268                    catch (Exception e) {
1269                            return;
1270                    }
1271    
1272                    try {
1273                            SitesUtil.applyLayoutPrototype(layoutPrototype, layout, true);
1274                    }
1275                    catch (Exception e) {
1276                            _log.error(e, e);
1277    
1278                            prototypeTypeSettingsProperties.setProperty(
1279                                    MERGE_FAIL_COUNT, String.valueOf(++mergeFailCount));
1280    
1281                            // Invoke updateImpl so that we do not trigger the listeners
1282    
1283                            LayoutUtil.updateImpl(layoutPrototypeLayout);
1284                    }
1285                    finally {
1286                            LockLocalServiceUtil.unlock(
1287                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
1288                                    String.valueOf(layout.getPlid()), owner, false);
1289                    }
1290            }
1291    
1292            protected static Map<String, String[]> getLayoutSetPrototypesParameters(
1293                    boolean importData) {
1294    
1295                    Map<String, String[]> parameterMap =
1296                            new LinkedHashMap<String, String[]>();
1297    
1298                    parameterMap.put(
1299                            PortletDataHandlerKeys.CATEGORIES,
1300                            new String[] {Boolean.TRUE.toString()});
1301                    parameterMap.put(
1302                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1303                            new String[] {Boolean.FALSE.toString()});
1304                    parameterMap.put(
1305                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1306                            new String[] {Boolean.FALSE.toString()});
1307                    parameterMap.put(
1308                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
1309                            new String[] {Boolean.TRUE.toString()});
1310                    parameterMap.put(
1311                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
1312                            new String[] {Boolean.TRUE.toString()});
1313                    parameterMap.put(
1314                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1315                            new String[] {Boolean.TRUE.toString()});
1316                    parameterMap.put(
1317                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
1318                            new String[] {
1319                                    PortletDataHandlerKeys.
1320                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
1321                            });
1322                    parameterMap.put(
1323                            PortletDataHandlerKeys.LOGO,
1324                            new String[] {Boolean.TRUE.toString()});
1325                    parameterMap.put(
1326                            PortletDataHandlerKeys.PERMISSIONS,
1327                            new String[] {Boolean.TRUE.toString()});
1328                    parameterMap.put(
1329                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS,
1330                            new String[] {Boolean.TRUE.toString()});
1331                    parameterMap.put(
1332                            PortletDataHandlerKeys.PORTLET_SETUP,
1333                            new String[] {Boolean.TRUE.toString()});
1334                    parameterMap.put(
1335                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
1336                            new String[] {Boolean.TRUE.toString()});
1337                    parameterMap.put(
1338                            PortletDataHandlerKeys.THEME,
1339                            new String[] {Boolean.FALSE.toString()});
1340                    parameterMap.put(
1341                            PortletDataHandlerKeys.THEME_REFERENCE,
1342                            new String[] {Boolean.TRUE.toString()});
1343                    parameterMap.put(
1344                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1345                            new String[] {Boolean.FALSE.toString()});
1346                    parameterMap.put(
1347                            PortletDataHandlerKeys.USER_ID_STRATEGY,
1348                            new String[] {UserIdStrategy.CURRENT_USER_ID});
1349    
1350                    if (importData) {
1351                            parameterMap.put(
1352                                    PortletDataHandlerKeys.DATA_STRATEGY,
1353                                    new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
1354                            parameterMap.put(
1355                                    PortletDataHandlerKeys.PORTLET_DATA,
1356                                    new String[] {Boolean.TRUE.toString()});
1357                            parameterMap.put(
1358                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1359                                    new String[] {Boolean.TRUE.toString()});
1360                    }
1361                    else {
1362                            parameterMap.put(
1363                                    PortletDataHandlerKeys.PORTLET_DATA,
1364                                    new String[] {Boolean.FALSE.toString()});
1365                            parameterMap.put(
1366                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1367                                    new String[] {Boolean.FALSE.toString()});
1368                    }
1369    
1370                    return parameterMap;
1371            }
1372    
1373            protected static void importLayoutSetPrototype(
1374                            LayoutSetPrototype layoutSetPrototype, long groupId,
1375                            boolean privateLayout, Map<String, String[]> parameterMap,
1376                            boolean importData)
1377                    throws PortalException, SystemException {
1378    
1379                    File file = null;
1380    
1381                    StringBundler sb = new StringBundler(importData ? 4 : 3);
1382    
1383                    sb.append(_TEMP_DIR);
1384                    sb.append(layoutSetPrototype.getUuid());
1385    
1386                    if (importData) {
1387                            sb.append("-data");
1388                    }
1389    
1390                    sb.append(".lar");
1391    
1392                    File cacheFile = new File(sb.toString());
1393    
1394                    if (cacheFile.exists()) {
1395                            Date modifiedDate = layoutSetPrototype.getModifiedDate();
1396    
1397                            if (cacheFile.lastModified() >= modifiedDate.getTime()) {
1398                                    if (_log.isDebugEnabled()) {
1399                                            _log.debug(
1400                                                    "Using cached layout set prototype LAR file " +
1401                                                            cacheFile.getAbsolutePath());
1402                                    }
1403    
1404                                    file = cacheFile;
1405                            }
1406                    }
1407    
1408                    boolean newFile = false;
1409    
1410                    if (file == null) {
1411                            Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();
1412    
1413                            file = LayoutLocalServiceUtil.exportLayoutsAsFile(
1414                                    layoutSetPrototypeGroup.getGroupId(), true, null, parameterMap,
1415                                    null, null);
1416    
1417                            newFile = true;
1418                    }
1419    
1420                    long userId = UserLocalServiceUtil.getDefaultUserId(
1421                            layoutSetPrototype.getCompanyId());
1422    
1423                    LayoutLocalServiceUtil.importLayouts(
1424                            userId, groupId, privateLayout, parameterMap, file);
1425    
1426                    if (newFile) {
1427                            try {
1428                                    FileUtil.copyFile(file, cacheFile);
1429    
1430                                    if (_log.isDebugEnabled()) {
1431                                            _log.debug(
1432                                                    "Copied " + file.getAbsolutePath() + " to " +
1433                                                            cacheFile.getAbsolutePath());
1434                                    }
1435                            }
1436                            catch (Exception e) {
1437                                    _log.error(
1438                                            "Unable to copy file " + file.getAbsolutePath() + " to " +
1439                                                    cacheFile.getAbsolutePath(),
1440                                            e);
1441                            }
1442                    }
1443            }
1444    
1445            protected static void setLayoutSetPrototypeLinkEnabledParameter(
1446                    Map<String, String[]> parameterMap, LayoutSet targetLayoutSet,
1447                    ServiceContext serviceContext) {
1448    
1449                    PermissionChecker permissionChecker =
1450                            PermissionThreadLocal.getPermissionChecker();
1451    
1452                    if ((permissionChecker == null) ||
1453                            !PortalPermissionUtil.contains(
1454                                    permissionChecker, ActionKeys.UNLINK_LAYOUT_SET_PROTOTYPE)) {
1455    
1456                            return;
1457                    }
1458    
1459                    if (targetLayoutSet.isPrivateLayout()) {
1460                            boolean privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1461                                    serviceContext, "privateLayoutSetPrototypeLinkEnabled", true);
1462    
1463                            if (!privateLayoutSetPrototypeLinkEnabled) {
1464                                    privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1465                                            serviceContext, "layoutSetPrototypeLinkEnabled");
1466                            }
1467    
1468                            parameterMap.put(
1469                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1470                                    new String[] {
1471                                            String.valueOf(privateLayoutSetPrototypeLinkEnabled)
1472                                    });
1473                    }
1474                    else {
1475                            boolean publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1476                                    serviceContext, "publicLayoutSetPrototypeLinkEnabled");
1477    
1478                            if (!publicLayoutSetPrototypeLinkEnabled) {
1479                                    publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1480                                            serviceContext, "layoutSetPrototypeLinkEnabled", true);
1481                            }
1482    
1483                            parameterMap.put(
1484                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1485                                    new String[] {
1486                                            String.valueOf(publicLayoutSetPrototypeLinkEnabled)
1487                                    });
1488                    }
1489            }
1490    
1491            protected static void updateLayoutSetPrototypeLink(
1492                            long groupId, boolean privateLayout, long layoutSetPrototypeId,
1493                            boolean layoutSetPrototypeLinkEnabled)
1494                    throws Exception {
1495    
1496                    String layoutSetPrototypeUuid = null;
1497    
1498                    if (layoutSetPrototypeId > 0) {
1499                            LayoutSetPrototype layoutSetPrototype =
1500                                    LayoutSetPrototypeLocalServiceUtil.fetchLayoutSetPrototype(
1501                                            layoutSetPrototypeId);
1502    
1503                            if (layoutSetPrototype != null) {
1504                                    layoutSetPrototypeUuid = layoutSetPrototype.getUuid();
1505    
1506                                    // Merge without enabling the link
1507    
1508                                    if (!layoutSetPrototypeLinkEnabled &&
1509                                            (layoutSetPrototypeId > 0)) {
1510    
1511                                            Map<String, String[]> parameterMap =
1512                                                    getLayoutSetPrototypesParameters(true);
1513    
1514                                            importLayoutSetPrototype(
1515                                                    layoutSetPrototype, groupId, privateLayout,
1516                                                    parameterMap, true);
1517                                    }
1518                            }
1519                    }
1520    
1521                    LayoutSetServiceUtil.updateLayoutSetPrototypeLinkEnabled(
1522                            groupId, privateLayout, layoutSetPrototypeLinkEnabled,
1523                            layoutSetPrototypeUuid);
1524    
1525                    LayoutLocalServiceUtil.updatePriorities(groupId, privateLayout);
1526            }
1527    
1528            private static final String _TEMP_DIR =
1529                    SystemProperties.get(SystemProperties.TMP_DIR) +
1530                            "/liferay/layout_set_prototype/";
1531    
1532            private static Log _log = LogFactoryUtil.getLog(SitesUtil.class);
1533    
1534    }