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