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.events.EventsProcessorUtil;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.language.LanguageUtil;
021    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
022    import com.liferay.portal.kernel.lar.UserIdStrategy;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.util.FileUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.ParamUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.StringBundler;
030    import com.liferay.portal.kernel.util.SystemProperties;
031    import com.liferay.portal.kernel.util.UnicodeProperties;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
034    import com.liferay.portal.model.Group;
035    import com.liferay.portal.model.Layout;
036    import com.liferay.portal.model.LayoutConstants;
037    import com.liferay.portal.model.LayoutPrototype;
038    import com.liferay.portal.model.LayoutSet;
039    import com.liferay.portal.model.LayoutSetPrototype;
040    import com.liferay.portal.model.LayoutTypePortlet;
041    import com.liferay.portal.model.Lock;
042    import com.liferay.portal.model.PortletConstants;
043    import com.liferay.portal.model.ResourceConstants;
044    import com.liferay.portal.model.Role;
045    import com.liferay.portal.model.RoleConstants;
046    import com.liferay.portal.model.UserGroup;
047    import com.liferay.portal.model.impl.VirtualLayout;
048    import com.liferay.portal.security.auth.PrincipalException;
049    import com.liferay.portal.security.permission.ActionKeys;
050    import com.liferay.portal.security.permission.PermissionChecker;
051    import com.liferay.portal.security.permission.PermissionThreadLocal;
052    import com.liferay.portal.security.permission.ResourceActionsUtil;
053    import com.liferay.portal.service.GroupServiceUtil;
054    import com.liferay.portal.service.LayoutLocalServiceUtil;
055    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
056    import com.liferay.portal.service.LayoutServiceUtil;
057    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
058    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
059    import com.liferay.portal.service.LayoutSetServiceUtil;
060    import com.liferay.portal.service.LockLocalServiceUtil;
061    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
062    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
063    import com.liferay.portal.service.RoleLocalServiceUtil;
064    import com.liferay.portal.service.ServiceContext;
065    import com.liferay.portal.service.ServiceContextFactory;
066    import com.liferay.portal.service.ServiceContextThreadLocal;
067    import com.liferay.portal.service.UserGroupLocalServiceUtil;
068    import com.liferay.portal.service.UserLocalServiceUtil;
069    import com.liferay.portal.service.impl.LayoutLocalServiceVirtualLayoutsAdvice;
070    import com.liferay.portal.service.permission.GroupPermissionUtil;
071    import com.liferay.portal.service.permission.LayoutPermissionUtil;
072    import com.liferay.portal.service.permission.PortalPermissionUtil;
073    import com.liferay.portal.service.permission.PortletPermissionUtil;
074    import com.liferay.portal.service.persistence.LayoutSetUtil;
075    import com.liferay.portal.service.persistence.LayoutUtil;
076    import com.liferay.portal.theme.PortletDisplay;
077    import com.liferay.portal.theme.ThemeDisplay;
078    import com.liferay.portal.util.LayoutSettings;
079    import com.liferay.portal.util.PortalUtil;
080    import com.liferay.portal.util.PortletKeys;
081    import com.liferay.portal.util.PropsValues;
082    import com.liferay.portal.util.WebKeys;
083    import com.liferay.portlet.PortletPreferencesFactoryUtil;
084    import com.liferay.portlet.PortletPreferencesImpl;
085    
086    import java.io.File;
087    import java.io.InputStream;
088    
089    import java.util.Date;
090    import java.util.LinkedHashMap;
091    import java.util.List;
092    import java.util.Locale;
093    import java.util.Map;
094    
095    import javax.portlet.ActionRequest;
096    import javax.portlet.ActionResponse;
097    import javax.portlet.PortletPreferences;
098    import javax.portlet.PortletURL;
099    import javax.portlet.RenderRequest;
100    import javax.portlet.RenderResponse;
101    
102    import javax.servlet.http.HttpServletRequest;
103    import javax.servlet.http.HttpServletResponse;
104    
105    /**
106     * @author Raymond Augé
107     * @author Ryan Park
108     * @author Zsolt Berentey
109     */
110    public class SitesUtil {
111    
112            public static void addPortletBreadcrumbEntries(
113                            Group group, String pagesName, PortletURL redirectURL,
114                            HttpServletRequest request, RenderResponse renderResponse)
115                    throws Exception {
116    
117                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
118                            com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
119    
120                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
121    
122                    String portletName = portletDisplay.getPortletName();
123    
124                    if ((renderResponse == null) ||
125                            portletName.equals(PortletKeys.GROUP_PAGES) ||
126                            portletName.equals(PortletKeys.MY_PAGES)) {
127    
128                            return;
129                    }
130    
131                    Locale locale = themeDisplay.getLocale();
132    
133                    if (group.isLayoutPrototype()) {
134                            PortalUtil.addPortletBreadcrumbEntry(
135                                    request, LanguageUtil.get(locale, "page-template"), null);
136    
137                            PortalUtil.addPortletBreadcrumbEntry(
138                                    request, group.getDescriptiveName(), redirectURL.toString());
139                    }
140                    else {
141                            PortalUtil.addPortletBreadcrumbEntry(
142                                    request, group.getDescriptiveName(), null);
143                    }
144    
145                    if (!group.isLayoutPrototype()) {
146                            PortalUtil.addPortletBreadcrumbEntry(
147                                    request, LanguageUtil.get(locale, pagesName),
148                                    redirectURL.toString());
149                    }
150            }
151    
152            public static void applyLayoutPrototype(
153                            LayoutPrototype layoutPrototype, Layout targetLayout,
154                            boolean linkEnabled)
155                    throws Exception {
156    
157                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
158    
159                    ServiceContext serviceContext =
160                            ServiceContextThreadLocal.getServiceContext();
161    
162                    serviceContext.setAttribute("layoutPrototypeLinkEnabled", linkEnabled);
163                    serviceContext.setAttribute(
164                            "layoutPrototypeUuid", layoutPrototype.getUuid());
165    
166                    targetLayout = LayoutLocalServiceUtil.updateLayout(
167                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
168                            targetLayout.getLayoutId(), targetLayout.getParentLayoutId(),
169                            targetLayout.getNameMap(), targetLayout.getTitleMap(),
170                            targetLayout.getDescriptionMap(), targetLayout.getKeywordsMap(),
171                            targetLayout.getRobotsMap(), layoutPrototypeLayout.getType(),
172                            targetLayout.getHidden(), targetLayout.getFriendlyURL(),
173                            targetLayout.getIconImage(), null, serviceContext);
174    
175                    targetLayout = LayoutLocalServiceUtil.updateLayout(
176                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
177                            targetLayout.getLayoutId(),
178                            layoutPrototypeLayout.getTypeSettings());
179    
180                    copyPortletPermissions(targetLayout, layoutPrototypeLayout);
181    
182                    copyPortletSetups(layoutPrototypeLayout, targetLayout);
183    
184                    copyLookAndFeel(targetLayout, layoutPrototypeLayout);
185    
186                    targetLayout = LayoutLocalServiceUtil.getLayout(targetLayout.getPlid());
187    
188                    UnicodeProperties typeSettingsProperties =
189                            targetLayout.getTypeSettingsProperties();
190    
191                    typeSettingsProperties.setProperty(
192                            "last-merge-time",
193                            String.valueOf(targetLayout.getModifiedDate().getTime()));
194    
195                    LayoutLocalServiceUtil.updateLayout(targetLayout, false);
196    
197                    UnicodeProperties prototypeTypeSettingsProperties =
198                            layoutPrototypeLayout.getTypeSettingsProperties();
199    
200                    prototypeTypeSettingsProperties.setProperty("merge-fail-count", "0");
201    
202                    LayoutLocalServiceUtil.updateLayout(layoutPrototypeLayout, false);
203            }
204    
205            public static void copyLayout(
206                            long userId, Layout sourceLayout, Layout targetLayout,
207                            ServiceContext serviceContext)
208                    throws Exception {
209    
210                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
211                            serviceContext);
212    
213                    parameterMap.put(
214                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
215                            new String[]{Boolean.FALSE.toString()});
216    
217                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
218                            sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
219                            new long[] {sourceLayout.getLayoutId()}, parameterMap, null, null);
220    
221                    try {
222                            LayoutLocalServiceUtil.importLayouts(
223                                    userId, targetLayout.getGroupId(),
224                                    targetLayout.isPrivateLayout(), parameterMap, file);
225                    }
226                    finally {
227                            file.delete();
228                    }
229            }
230    
231            public static void copyLookAndFeel(Layout targetLayout, Layout sourceLayout)
232                    throws Exception {
233    
234                    LayoutLocalServiceUtil.updateLookAndFeel(
235                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
236                            targetLayout.getLayoutId(), sourceLayout.getThemeId(),
237                            sourceLayout.getColorSchemeId(), sourceLayout.getCss(), false);
238    
239                    LayoutLocalServiceUtil.updateLookAndFeel(
240                            targetLayout.getGroupId(), targetLayout.isPrivateLayout(),
241                            targetLayout.getLayoutId(), sourceLayout.getWapThemeId(),
242                            sourceLayout.getWapColorSchemeId(), sourceLayout.getCss(), true);
243            }
244    
245            public static void copyPortletPermissions(
246                    Layout targetLayout, Layout sourceLayout)
247                    throws Exception {
248    
249                    long companyId = targetLayout.getCompanyId();
250    
251                    List<Role> roles = RoleLocalServiceUtil.getRoles(companyId);
252    
253                    LayoutTypePortlet sourceLayoutTypePortlet =
254                            (LayoutTypePortlet)sourceLayout.getLayoutType();
255    
256                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
257    
258                    for (String sourcePortletId : sourcePortletIds) {
259                            String resourceName = PortletConstants.getRootPortletId(
260                                    sourcePortletId);
261    
262                            String sourceResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
263                                    sourceLayout.getPlid(), sourcePortletId);
264    
265                            String targetResourcePrimKey = PortletPermissionUtil.getPrimaryKey(
266                                    targetLayout.getPlid(), sourcePortletId);
267    
268                            List<String> actionIds =
269                                    ResourceActionsUtil.getPortletResourceActions(resourceName);
270    
271                            for (Role role : roles) {
272                                    String roleName = role.getName();
273    
274                                    if (roleName.equals(RoleConstants.ADMINISTRATOR)) {
275                                            continue;
276                                    }
277    
278                                    List<String> actions =
279                                            ResourcePermissionLocalServiceUtil.
280                                                    getAvailableResourcePermissionActionIds(
281                                                            companyId, resourceName,
282                                                            ResourceConstants.SCOPE_INDIVIDUAL,
283                                                            sourceResourcePrimKey, role.getRoleId(), actionIds);
284    
285                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
286                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
287                                            targetResourcePrimKey, role.getRoleId(),
288                                            actions.toArray(new String[actions.size()]));
289                            }
290                    }
291            }
292    
293            public static void copyPortletSetups(
294                            Layout sourceLayout, Layout targetLayout)
295                    throws Exception {
296    
297                    LayoutTypePortlet sourceLayoutTypePortlet =
298                            (LayoutTypePortlet)sourceLayout.getLayoutType();
299    
300                    List<String> sourcePortletIds = sourceLayoutTypePortlet.getPortletIds();
301    
302                    for (String sourcePortletId : sourcePortletIds) {
303                            PortletPreferences sourcePreferences =
304                                    PortletPreferencesFactoryUtil.getPortletSetup(
305                                            sourceLayout, sourcePortletId, null);
306    
307                            PortletPreferencesImpl sourcePreferencesImpl =
308                                    (PortletPreferencesImpl)sourcePreferences;
309    
310                            PortletPreferences targetPreferences =
311                                    PortletPreferencesFactoryUtil.getPortletSetup(
312                                            targetLayout, sourcePortletId, null);
313    
314                            PortletPreferencesImpl targetPreferencesImpl =
315                                    (PortletPreferencesImpl)targetPreferences;
316    
317                            PortletPreferencesLocalServiceUtil.updatePreferences(
318                                    targetPreferencesImpl.getOwnerId(),
319                                    targetPreferencesImpl.getOwnerType(),
320                                    targetPreferencesImpl.getPlid(), sourcePortletId,
321                                    sourcePreferences);
322    
323                            if ((sourcePreferencesImpl.getOwnerId() !=
324                                            PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
325                                    (sourcePreferencesImpl.getOwnerType() !=
326                                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT)) {
327    
328                                    sourcePreferences =
329                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
330                                                    sourceLayout, sourcePortletId);
331    
332                                    sourcePreferencesImpl =
333                                            (PortletPreferencesImpl)sourcePreferences;
334    
335                                    targetPreferences =
336                                            PortletPreferencesFactoryUtil.getLayoutPortletSetup(
337                                                    targetLayout, sourcePortletId);
338    
339                                    targetPreferencesImpl =
340                                            (PortletPreferencesImpl)targetPreferences;
341    
342                                    PortletPreferencesLocalServiceUtil.updatePreferences(
343                                            targetPreferencesImpl.getOwnerId(),
344                                            targetPreferencesImpl.getOwnerType(),
345                                            targetPreferencesImpl.getPlid(), sourcePortletId,
346                                            sourcePreferences);
347                            }
348                    }
349            }
350    
351            public static void copyTypeSettings(Group sourceGroup, Group targetGroup)
352                    throws Exception {
353    
354                    GroupServiceUtil.updateGroup(
355                            targetGroup.getGroupId(), sourceGroup.getTypeSettings());
356            }
357    
358            public static Object[] deleteLayout(
359                            ActionRequest actionRequest, ActionResponse actionResponse)
360                    throws Exception {
361    
362                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
363                            actionRequest);
364                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
365                            actionResponse);
366    
367                    return deleteLayout(request, response);
368            }
369    
370            public static Object[] deleteLayout(
371                            HttpServletRequest request, HttpServletResponse response)
372                    throws Exception {
373    
374                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
375                            WebKeys.THEME_DISPLAY);
376    
377                    PermissionChecker permissionChecker =
378                            themeDisplay.getPermissionChecker();
379    
380                    long plid = ParamUtil.getLong(request, "plid");
381    
382                    long groupId = ParamUtil.getLong(request, "groupId");
383                    boolean privateLayout = ParamUtil.getBoolean(request, "privateLayout");
384                    long layoutId = ParamUtil.getLong(request, "layoutId");
385    
386                    Layout layout = null;
387    
388                    if (plid <= 0) {
389                            layout = LayoutLocalServiceUtil.getLayout(
390                                    groupId, privateLayout, layoutId);
391                    }
392                    else {
393                            layout = LayoutLocalServiceUtil.getLayout(plid);
394    
395                            groupId = layout.getGroupId();
396                            privateLayout = layout.isPrivateLayout();
397                            layoutId = layout.getLayoutId();
398                    }
399    
400                    Group group = layout.getGroup();
401                    String oldFriendlyURL = layout.getFriendlyURL();
402    
403                    if (group.isStagingGroup() &&
404                            !GroupPermissionUtil.contains(
405                                    permissionChecker, groupId, ActionKeys.MANAGE_STAGING) &&
406                            !GroupPermissionUtil.contains(
407                                    permissionChecker, groupId, ActionKeys.PUBLISH_STAGING)) {
408    
409                            throw new PrincipalException();
410                    }
411    
412                    if (LayoutPermissionUtil.contains(
413                                    permissionChecker, layout, ActionKeys.DELETE)) {
414    
415                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
416    
417                            EventsProcessorUtil.process(
418                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_DELETE,
419                                    layoutSettings.getConfigurationActionDelete(), request,
420                                    response);
421                    }
422    
423                    LayoutSet layoutSet = layout.getLayoutSet();
424    
425                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
426                            request);
427    
428                    LayoutServiceUtil.deleteLayout(
429                            groupId, privateLayout, layoutId, serviceContext);
430    
431                    long newPlid = layout.getParentPlid();
432    
433                    if (newPlid <= 0) {
434                            Layout firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
435                                    layoutSet.getGroupId(), layoutSet.getPrivateLayout(),
436                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
437    
438                            if (firstLayout != null) {
439                                    newPlid = firstLayout.getPlid();
440                            }
441                    }
442    
443                    return new Object[] {group, oldFriendlyURL, newPlid};
444            }
445    
446            public static void deleteLayout(
447                            RenderRequest renderRequest, RenderResponse renderResponse)
448                    throws Exception {
449    
450                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
451                            renderRequest);
452                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
453                            renderResponse);
454    
455                    deleteLayout(request, response);
456            }
457    
458            public static File exportLayoutSetPrototype(
459                            LayoutSetPrototype layoutSetPrototype,
460                            ServiceContext serviceContext)
461                    throws PortalException, SystemException {
462    
463                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
464    
465                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
466                            serviceContext);
467    
468                    return LayoutLocalServiceUtil.exportLayoutsAsFile(
469                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), null,
470                            parameterMap, null, null);
471            }
472    
473            public static Layout getLayoutSetPrototypeLayout(Layout layout) {
474                    try {
475                            LayoutSet layoutSet = layout.getLayoutSet();
476    
477                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
478                                    return null;
479                            }
480    
481                            LayoutSetPrototype layoutSetPrototype =
482                                    LayoutSetPrototypeLocalServiceUtil.
483                                            getLayoutSetPrototypeByUuid(
484                                                    layoutSet.getLayoutSetPrototypeUuid());
485    
486                            Group group = layoutSetPrototype.getGroup();
487    
488                            return LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
489                                    layout.getSourcePrototypeLayoutUuid(), group.getGroupId());
490                    }
491                    catch (Exception e) {
492                            _log.error(
493                                    "Unable to fetch the the layout set prototype's layout", e);
494                    }
495    
496                    return null;
497            }
498    
499            public static Map<String, String[]> getLayoutSetPrototypeParameters(
500                    ServiceContext serviceContext) {
501    
502                    Map<String, String[]> parameterMap =
503                            new LinkedHashMap<String, String[]>();
504    
505                    parameterMap.put(
506                            PortletDataHandlerKeys.CATEGORIES,
507                            new String[] {Boolean.TRUE.toString()});
508                    parameterMap.put(
509                            PortletDataHandlerKeys.DATA_STRATEGY,
510                            new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
511                    parameterMap.put(
512                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
513                            new String[] {Boolean.TRUE.toString()});
514                    parameterMap.put(
515                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
516                            new String[] {Boolean.FALSE.toString()});
517                    parameterMap.put(
518                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
519                            new String[] {Boolean.TRUE.toString()});
520                    parameterMap.put(
521                            PortletDataHandlerKeys.LAYOUT_SET_SETTINGS,
522                            new String[] {Boolean.FALSE.toString()});
523                    parameterMap.put(
524                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
525                            new String[] {
526                                    PortletDataHandlerKeys.
527                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
528                            });
529                    parameterMap.put(
530                            PortletDataHandlerKeys.LOGO,
531                            new String[] {Boolean.FALSE.toString()});
532                    parameterMap.put(
533                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
534                            new String[] {Boolean.TRUE.toString()});
535                    parameterMap.put(
536                            PortletDataHandlerKeys.PERMISSIONS,
537                            new String[] {Boolean.TRUE.toString()});
538                    parameterMap.put(
539                            PortletDataHandlerKeys.PORTLET_DATA,
540                            new String[] {Boolean.TRUE.toString()});
541                    parameterMap.put(
542                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
543                            new String[] {Boolean.TRUE.toString()});
544                    parameterMap.put(
545                            PortletDataHandlerKeys.PORTLET_SETUP,
546                            new String[] {Boolean.TRUE.toString()});
547                    parameterMap.put(
548                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
549                            new String[] {Boolean.TRUE.toString()});
550                    parameterMap.put(
551                            PortletDataHandlerKeys.THEME,
552                            new String[] {Boolean.FALSE.toString()});
553                    parameterMap.put(
554                            PortletDataHandlerKeys.THEME_REFERENCE,
555                            new String[] {Boolean.TRUE.toString()});
556                    parameterMap.put(
557                            PortletDataHandlerKeys.USER_ID_STRATEGY,
558                            new String[] {UserIdStrategy.CURRENT_USER_ID});
559                    parameterMap.put(
560                            PortletDataHandlerKeys.USER_PERMISSIONS,
561                            new String[] {Boolean.FALSE.toString()});
562    
563                    return parameterMap;
564            }
565    
566            public static void importLayoutSetPrototype(
567                            LayoutSetPrototype layoutSetPrototype, InputStream inputStream,
568                            ServiceContext serviceContext)
569                    throws PortalException, SystemException {
570    
571                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
572    
573                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
574                            serviceContext);
575    
576                    setLayoutSetPrototypeLinkEnabledParameter(
577                            parameterMap, layoutSet, serviceContext);
578    
579                    LayoutServiceUtil.importLayouts(
580                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(), parameterMap,
581                            inputStream);
582            }
583    
584            public static boolean isLayoutDeleteable(Layout layout) {
585                    try {
586                            if (layout instanceof VirtualLayout) {
587                                    return false;
588                            }
589    
590                            if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
591                                    return true;
592                            }
593    
594                            LayoutSet layoutSet = layout.getLayoutSet();
595    
596                            if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
597                                    return true;
598                            }
599    
600                            if (LayoutLocalServiceUtil.hasLayoutSetPrototypeLayout(
601                                            layoutSet.getLayoutSetPrototypeUuid(),
602                                            layout.getSourcePrototypeLayoutUuid())) {
603    
604                                    return false;
605                            }
606                    }
607                    catch (Exception e) {
608                            if (_log.isDebugEnabled()) {
609                                    _log.debug(e, e);
610                            }
611                    }
612    
613                    return true;
614            }
615    
616            public static boolean isLayoutModifiedSinceLastMerge(Layout layout)
617                    throws PortalException, SystemException {
618    
619                    if ((layout == null) ||
620                            Validator.isNull(layout.getSourcePrototypeLayoutUuid()) ||
621                            layout.isLayoutPrototypeLinkActive()) {
622    
623                            return false;
624                    }
625    
626                    LayoutSet existingLayoutSet = layout.getLayoutSet();
627    
628                    long lastMergeTime = GetterUtil.getLong(
629                            existingLayoutSet.getSettingsProperty("last-merge-time"));
630    
631                    Date existingLayoutModifiedDate = layout.getModifiedDate();
632    
633                    if ((existingLayoutModifiedDate != null) &&
634                            (existingLayoutModifiedDate.getTime() > lastMergeTime) &&
635                            isLayoutUpdateable(layout)) {
636    
637                            return true;
638                    }
639    
640                    return false;
641            }
642    
643            public static boolean isLayoutSetPrototypeUpdateable(LayoutSet layoutSet) {
644                    if (!layoutSet.isLayoutSetPrototypeLinkActive()) {
645                            return true;
646                    }
647    
648                    try {
649                            LayoutSetPrototype layoutSetPrototype =
650                                    LayoutSetPrototypeLocalServiceUtil.
651                                            getLayoutSetPrototypeByUuid(
652                                                    layoutSet.getLayoutSetPrototypeUuid());
653    
654                            String layoutsUpdateable = layoutSetPrototype.getSettingsProperty(
655                                    "layoutsUpdateable");
656    
657                            if (Validator.isNotNull(layoutsUpdateable)) {
658                                    return GetterUtil.getBoolean(layoutsUpdateable, true);
659                            }
660                    }
661                    catch (Exception e) {
662                            if (_log.isDebugEnabled()) {
663                                    _log.debug(e, e);
664                            }
665                    }
666    
667                    return true;
668            }
669    
670            public static boolean isLayoutUpdateable(Layout layout) {
671                    try {
672                            if (layout instanceof VirtualLayout) {
673                                    return false;
674                            }
675    
676                            if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
677                                    Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
678    
679                                    return true;
680                            }
681    
682                            LayoutSet layoutSet = layout.getLayoutSet();
683    
684                            if (layoutSet.isLayoutSetPrototypeLinkActive()) {
685                                    boolean layoutSetPrototypeUpdateable =
686                                            isLayoutSetPrototypeUpdateable(layoutSet);
687    
688                                    if (!layoutSetPrototypeUpdateable) {
689                                            return false;
690                                    }
691    
692                                    Layout layoutSetPrototypeLayout = getLayoutSetPrototypeLayout(
693                                            layout);
694    
695                                    UnicodeProperties typeSettingsProperties =
696                                            layoutSetPrototypeLayout.getTypeSettingsProperties();
697    
698                                    String layoutUpdateable = typeSettingsProperties.getProperty(
699                                            "layoutUpdateable");
700    
701                                    if (Validator.isNull(layoutUpdateable)) {
702                                            return true;
703                                    }
704    
705                                    return GetterUtil.getBoolean(layoutUpdateable);
706                            }
707                    }
708                    catch (Exception e) {
709                            if (_log.isDebugEnabled()) {
710                                    _log.debug(e, e);
711                            }
712                    }
713    
714                    return true;
715            }
716    
717            public static boolean isUserGroupLayoutSetViewable(
718                            PermissionChecker permissionChecker, Group userGroupGroup)
719                    throws PortalException, SystemException {
720    
721                    if (!userGroupGroup.isUserGroup()) {
722                            return false;
723                    }
724    
725                    if (GroupPermissionUtil.contains(
726                                    permissionChecker, userGroupGroup.getGroupId(),
727                                    ActionKeys.VIEW)) {
728    
729                            return true;
730                    }
731    
732                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
733                            userGroupGroup.getClassPK());
734    
735                    if (UserLocalServiceUtil.hasUserGroupUser(
736                                    userGroup.getUserGroupId(), permissionChecker.getUserId())) {
737    
738                            return true;
739                    }
740                    else {
741                            return false;
742                    }
743            }
744    
745            public static void mergeLayoutProtypeLayout(Group group, Layout layout)
746                    throws Exception {
747    
748                    if (!layout.isLayoutPrototypeLinkActive() ||
749                            group.isLayoutPrototype() || group.hasStagingGroup()) {
750    
751                            return;
752                    }
753    
754                    UnicodeProperties typeSettingsProperties =
755                            layout.getTypeSettingsProperties();
756    
757                    long lastMergeTime = GetterUtil.getLong(
758                            typeSettingsProperties.getProperty("last-merge-time"));
759    
760                    LayoutPrototype layoutPrototype =
761                            LayoutPrototypeLocalServiceUtil.getLayoutPrototypeByUuid(
762                                    layout.getLayoutPrototypeUuid());
763    
764                    Layout layoutPrototypeLayout = layoutPrototype.getLayout();
765    
766                    Date modifiedDate = layoutPrototypeLayout.getModifiedDate();
767    
768                    if (lastMergeTime >= modifiedDate.getTime()) {
769                            return;
770                    }
771    
772                    UnicodeProperties prototypeTypeSettingsProperties =
773                            layoutPrototypeLayout.getTypeSettingsProperties();
774    
775                    int mergeFailCount = GetterUtil.getInteger(
776                            prototypeTypeSettingsProperties.getProperty("merge-fail-count"));
777    
778                    if (mergeFailCount >
779                            PropsValues.LAYOUT_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
780    
781                            return;
782                    }
783    
784                    String owner = PortalUUIDUtil.generate();
785    
786                    try {
787                            Lock lock = LockLocalServiceUtil.lock(
788                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
789                                    String.valueOf(layout.getPlid()), owner, false);
790    
791                            // Double deep check
792    
793                            if (!owner.equals(lock.getOwner())) {
794                                    Date createDate = lock.getCreateDate();
795    
796                                    if (((System.currentTimeMillis() - createDate.getTime()) >=
797                                            PropsValues.LAYOUT_PROTOTYPE_MERGE_LOCK_MAX_TIME)) {
798    
799                                            // Acquire lock if the lock is older than the lock max time
800    
801                                            lock = LockLocalServiceUtil.lock(
802                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
803                                                    String.valueOf(layout.getPlid()), lock.getOwner(),
804                                                    owner, false);
805    
806                                            // Check if acquiring the lock succeeded or if another
807                                            // process has the lock
808    
809                                            if (!owner.equals(lock.getOwner())) {
810                                                    return;
811                                            }
812                                    }
813                                    else {
814                                            return;
815                                    }
816                            }
817                    }
818                    catch (Exception e) {
819                            return;
820                    }
821    
822                    try {
823                            SitesUtil.applyLayoutPrototype(layoutPrototype, layout, true);
824                    }
825                    catch (Exception e) {
826                            _log.error(e, e);
827    
828                            prototypeTypeSettingsProperties.setProperty(
829                                    "merge-fail-count", String.valueOf(++mergeFailCount));
830    
831                            // Invoke updateImpl so that we do not trigger the listeners
832    
833                            LayoutUtil.updateImpl(layoutPrototypeLayout, false);
834                    }
835                    finally {
836                            LockLocalServiceUtil.unlock(
837                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
838                                    String.valueOf(layout.getPlid()), owner, false);
839                    }
840            }
841    
842            public static void mergeLayoutSetProtypeLayouts(
843                    Group group, LayoutSet layoutSet)
844                    throws Exception {
845    
846                    if (!layoutSet.isLayoutSetPrototypeLinkActive() ||
847                            group.isLayoutPrototype() || group.isLayoutSetPrototype()) {
848    
849                            return;
850                    }
851    
852                    UnicodeProperties settingsProperties =
853                            layoutSet.getSettingsProperties();
854    
855                    long lastMergeTime = GetterUtil.getLong(
856                            settingsProperties.getProperty("last-merge-time"));
857    
858                    LayoutSetPrototype layoutSetPrototype =
859                            LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototypeByUuid(
860                                    layoutSet.getLayoutSetPrototypeUuid());
861    
862                    Date modifiedDate = layoutSetPrototype.getModifiedDate();
863    
864                    if (lastMergeTime >= modifiedDate.getTime()) {
865                            return;
866                    }
867    
868                    LayoutSet layoutSetPrototypeLayoutSet =
869                            layoutSetPrototype.getLayoutSet();
870    
871                    UnicodeProperties layoutSetPrototypeSettingsProperties =
872                            layoutSetPrototypeLayoutSet.getSettingsProperties();
873    
874                    int mergeFailCount = GetterUtil.getInteger(
875                            layoutSetPrototypeSettingsProperties.getProperty(
876                                    "merge-fail-count"));
877    
878                    if (mergeFailCount >
879                            PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_FAIL_THRESHOLD) {
880    
881                            if (_log.isWarnEnabled()) {
882                                    StringBundler sb = new StringBundler(6);
883    
884                                    sb.append("Merge not performed because the fail threshold was");
885                                    sb.append("reached for layoutSetPrototypeId ");
886                                    sb.append(layoutSetPrototype.getLayoutSetPrototypeId());
887                                    sb.append(" and layoutId ");
888                                    sb.append(layoutSetPrototypeLayoutSet.getLayoutSetId());
889                                    sb.append(". Update the count in the database to try again.");
890    
891                                    _log.warn(sb.toString());
892                            }
893    
894                            return;
895                    }
896    
897                    String owner = PortalUUIDUtil.generate();
898    
899                    try {
900                            Lock lock = LockLocalServiceUtil.lock(
901                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
902                                    String.valueOf(layoutSet.getLayoutSetId()), owner, false);
903    
904                            // Double deep check
905    
906                            if (!owner.equals(lock.getOwner())) {
907                                    Date createDate = lock.getCreateDate();
908    
909                                    if ((System.currentTimeMillis() - createDate.getTime()) >=
910                                            PropsValues.LAYOUT_SET_PROTOTYPE_MERGE_LOCK_MAX_TIME) {
911    
912                                            // Acquire lock if the lock is older than the lock max time
913    
914                                            lock = LockLocalServiceUtil.lock(
915                                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
916                                                    String.valueOf(layoutSet.getLayoutSetId()),
917                                                    lock.getOwner(), owner, false);
918    
919                                            // Check if acquiring the lock succeeded or if another
920                                            // process has the lock
921    
922                                            if (!owner.equals(lock.getOwner())) {
923                                                    return;
924                                            }
925                                    }
926                                    else {
927                                            return;
928                                    }
929                            }
930                    }
931                    catch (Exception e) {
932                            return;
933                    }
934    
935                    try {
936                            Map<String, String[]> parameterMap = null;
937    
938                            boolean importData = true;
939    
940                            if (lastMergeTime > 0) {
941                                    importData = false;
942                            }
943    
944                            parameterMap = getLayoutSetPrototypesParameters(importData);
945    
946                            importLayoutSetPrototype(
947                                    layoutSetPrototype, layoutSet.getGroupId(),
948                                    layoutSet.isPrivateLayout(), parameterMap, importData);
949    
950                            layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
951                                    layoutSet.getGroupId(), layoutSet.isPrivateLayout());
952    
953                            settingsProperties = layoutSet.getSettingsProperties();
954    
955                            settingsProperties.setProperty(
956                                    "last-merge-time", String.valueOf(System.currentTimeMillis()));
957    
958                            LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet, false);
959                    }
960                    catch (Exception e) {
961                            _log.error(e, e);
962    
963                            layoutSetPrototypeSettingsProperties.setProperty(
964                                    "merge-fail-count", String.valueOf(++mergeFailCount));
965    
966                            // Invoke updateImpl so that we do not trigger the listeners
967    
968                            LayoutSetUtil.updateImpl(layoutSetPrototypeLayoutSet, false);
969                    }
970                    finally {
971                            LockLocalServiceUtil.unlock(
972                                    LayoutLocalServiceVirtualLayoutsAdvice.class.getName(),
973                                    String.valueOf(layoutSet.getLayoutSetId()), owner, false);
974                    }
975            }
976    
977            public static void resetPrototype(Layout layout)
978                    throws PortalException, SystemException {
979    
980                    layout.setModifiedDate(null);
981    
982                    LayoutLocalServiceUtil.updateLayout(layout, false);
983    
984                    LayoutSet layoutSet = layout.getLayoutSet();
985                    UnicodeProperties settingsProperties =
986                            layoutSet.getSettingsProperties();
987    
988                    settingsProperties.remove("last-merge-time");
989    
990                    LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet, false);
991            }
992    
993            public static void updateLayoutSetPrototypesLinks(
994                            Group group, long publicLayoutSetPrototypeId,
995                            long privateLayoutSetPrototypeId,
996                            boolean publicLayoutSetPrototypeLinkEnabled,
997                            boolean privateLayoutSetPrototypeLinkEnabled)
998                    throws Exception {
999    
1000                    updateLayoutSetPrototypeLink(
1001                            group.getGroupId(), true, privateLayoutSetPrototypeId,
1002                            privateLayoutSetPrototypeLinkEnabled);
1003                    updateLayoutSetPrototypeLink(
1004                            group.getGroupId(), false, publicLayoutSetPrototypeId,
1005                            publicLayoutSetPrototypeLinkEnabled);
1006            }
1007    
1008            protected static Map<String, String[]> getLayoutSetPrototypesParameters(
1009                    boolean importData) {
1010    
1011                    Map<String, String[]> parameterMap =
1012                            new LinkedHashMap<String, String[]>();
1013    
1014                    parameterMap.put(
1015                            PortletDataHandlerKeys.CATEGORIES,
1016                            new String[] {Boolean.TRUE.toString()});
1017                    parameterMap.put(
1018                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
1019                            new String[] {Boolean.FALSE.toString()});
1020                    parameterMap.put(
1021                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
1022                            new String[] {Boolean.FALSE.toString()});
1023                    parameterMap.put(
1024                            PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE,
1025                            new String[] {Boolean.TRUE.toString()});
1026                    parameterMap.put(
1027                            PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1028                            new String[] {Boolean.TRUE.toString()});
1029                    parameterMap.put(
1030                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
1031                            new String[] {
1032                                    PortletDataHandlerKeys.
1033                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
1034                            });
1035                    parameterMap.put(
1036                            PortletDataHandlerKeys.PERMISSIONS,
1037                            new String[] {Boolean.TRUE.toString()});
1038                    parameterMap.put(
1039                            PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS,
1040                            new String[] {Boolean.TRUE.toString()});
1041                    parameterMap.put(
1042                            PortletDataHandlerKeys.PORTLET_SETUP,
1043                            new String[] {Boolean.TRUE.toString()});
1044                    parameterMap.put(
1045                            PortletDataHandlerKeys.PORTLET_SETUP_ALL,
1046                            new String[] {Boolean.TRUE.toString()});
1047                    parameterMap.put(
1048                            PortletDataHandlerKeys.THEME,
1049                            new String[] {Boolean.FALSE.toString()});
1050                    parameterMap.put(
1051                            PortletDataHandlerKeys.THEME_REFERENCE,
1052                            new String[] {Boolean.TRUE.toString()});
1053                    parameterMap.put(
1054                            PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE,
1055                            new String[] {Boolean.FALSE.toString()});
1056                    parameterMap.put(
1057                            PortletDataHandlerKeys.USER_ID_STRATEGY,
1058                            new String[] {UserIdStrategy.CURRENT_USER_ID});
1059    
1060                    if (importData) {
1061                            parameterMap.put(
1062                                    PortletDataHandlerKeys.DATA_STRATEGY,
1063                                    new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
1064                            parameterMap.put(
1065                                    PortletDataHandlerKeys.PORTLET_DATA,
1066                                    new String[] {Boolean.TRUE.toString()});
1067                            parameterMap.put(
1068                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1069                                    new String[] {Boolean.TRUE.toString()});
1070                    }
1071                    else {
1072                            parameterMap.put(
1073                                    PortletDataHandlerKeys.PORTLET_DATA,
1074                                    new String[] {Boolean.FALSE.toString()});
1075                            parameterMap.put(
1076                                    PortletDataHandlerKeys.PORTLET_DATA_ALL,
1077                                    new String[] {Boolean.FALSE.toString()});
1078                    }
1079    
1080                    return parameterMap;
1081            }
1082    
1083            protected static void importLayoutSetPrototype(
1084                            LayoutSetPrototype layoutSetPrototype, long groupId,
1085                            boolean privateLayout, Map<String, String[]> parameterMap,
1086                            boolean importData)
1087                    throws PortalException, SystemException {
1088    
1089                    File file = null;
1090    
1091                    StringBundler sb = new StringBundler(importData ? 4 : 4);
1092    
1093                    sb.append(_TEMP_DIR);
1094                    sb.append(layoutSetPrototype.getUuid());
1095    
1096                    if (importData) {
1097                            sb.append("-data");
1098                    }
1099    
1100                    sb.append(".lar");
1101    
1102                    File cacheFile = new File(sb.toString());
1103    
1104                    if (cacheFile.exists()) {
1105                            Date modifiedDate = layoutSetPrototype.getModifiedDate();
1106    
1107                            if (cacheFile.lastModified() >= modifiedDate.getTime()) {
1108                                    if (_log.isDebugEnabled()) {
1109                                            _log.debug(
1110                                                    "Using cached layout set prototype LAR file " +
1111                                                            cacheFile.getAbsolutePath());
1112                                    }
1113    
1114                                    file = cacheFile;
1115                            }
1116                    }
1117    
1118                    boolean newFile = false;
1119    
1120                    if (file == null) {
1121                            Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();
1122    
1123                            file = LayoutLocalServiceUtil.exportLayoutsAsFile(
1124                                    layoutSetPrototypeGroup.getGroupId(), true, null, parameterMap,
1125                                    null, null);
1126    
1127                            newFile = true;
1128                    }
1129    
1130                    long userId = UserLocalServiceUtil.getDefaultUserId(
1131                            layoutSetPrototype.getCompanyId());
1132    
1133                    LayoutLocalServiceUtil.importLayouts(
1134                            userId, groupId, privateLayout, parameterMap, file);
1135    
1136                    if (newFile) {
1137                            try {
1138                                    FileUtil.copyFile(file, cacheFile);
1139    
1140                                    if (_log.isDebugEnabled()) {
1141                                            _log.debug(
1142                                                    "Copied " + file.getAbsolutePath() + " to " +
1143                                                            cacheFile.getAbsolutePath());
1144                                    }
1145                            }
1146                            catch (Exception e) {
1147                                    _log.error(
1148                                            "Unable to copy file " + file.getAbsolutePath() + " to " +
1149                                                    cacheFile.getAbsolutePath(),
1150                                            e);
1151                            }
1152                    }
1153            }
1154    
1155            protected static void setLayoutSetPrototypeLinkEnabledParameter(
1156                    Map<String, String[]> parameterMap, LayoutSet targetLayoutSet,
1157                    ServiceContext serviceContext) {
1158    
1159                    PermissionChecker permissionChecker =
1160                            PermissionThreadLocal.getPermissionChecker();
1161    
1162                    if ((permissionChecker == null) ||
1163                            !PortalPermissionUtil.contains(
1164                                    permissionChecker, ActionKeys.UNLINK_LAYOUT_SET_PROTOTYPE)) {
1165    
1166                            return;
1167                    }
1168    
1169                    if (targetLayoutSet.isPrivateLayout()) {
1170                            boolean privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1171                                    serviceContext, "privateLayoutSetPrototypeLinkEnabled", true);
1172    
1173                            if (!privateLayoutSetPrototypeLinkEnabled) {
1174                                    privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1175                                            serviceContext, "layoutSetPrototypeLinkEnabled");
1176                            }
1177    
1178                            parameterMap.put(
1179                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1180                                    new String[] {
1181                                            String.valueOf(privateLayoutSetPrototypeLinkEnabled)
1182                                    });
1183                    }
1184                    else {
1185                            boolean publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1186                                    serviceContext, "publicLayoutSetPrototypeLinkEnabled");
1187    
1188                            if (!publicLayoutSetPrototypeLinkEnabled) {
1189                                    publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
1190                                            serviceContext, "layoutSetPrototypeLinkEnabled", true);
1191                            }
1192    
1193                            parameterMap.put(
1194                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED,
1195                                    new String[] {
1196                                            String.valueOf(publicLayoutSetPrototypeLinkEnabled)
1197                                    });
1198                    }
1199            }
1200    
1201            protected static void updateLayoutSetPrototypeLink(
1202                            long groupId, boolean privateLayout, long layoutSetPrototypeId,
1203                            boolean layoutSetPrototypeLinkEnabled)
1204                    throws Exception {
1205    
1206                    String layoutSetPrototypeUuid = null;
1207    
1208                    if (layoutSetPrototypeId > 0) {
1209                            LayoutSetPrototype layoutSetPrototype =
1210                                    LayoutSetPrototypeLocalServiceUtil.fetchLayoutSetPrototype(
1211                                            layoutSetPrototypeId);
1212    
1213                            if (layoutSetPrototype != null) {
1214                                    layoutSetPrototypeUuid = layoutSetPrototype.getUuid();
1215    
1216                                    // Merge without enabling the link
1217    
1218                                    if (!layoutSetPrototypeLinkEnabled &&
1219                                            (layoutSetPrototypeId > 0)) {
1220    
1221                                            Map<String, String[]> parameterMap =
1222                                                    getLayoutSetPrototypesParameters(true);
1223    
1224                                            importLayoutSetPrototype(
1225                                                    layoutSetPrototype, groupId, privateLayout,
1226                                                    parameterMap, true);
1227                                    }
1228                            }
1229                    }
1230    
1231                    LayoutSetServiceUtil.updateLayoutSetPrototypeLinkEnabled(
1232                            groupId, privateLayout, layoutSetPrototypeLinkEnabled,
1233                            layoutSetPrototypeUuid);
1234            }
1235    
1236            private static final String _TEMP_DIR =
1237                    SystemProperties.get(SystemProperties.TMP_DIR) +
1238                            "/liferay/layout_set_prototype/";
1239    
1240            private static Log _log = LogFactoryUtil.getLog(SitesUtil.class);
1241    
1242    }