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.portal.service.impl;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.staging.MergeLayoutPrototypesThreadLocal;
020    import com.liferay.portal.kernel.util.ListUtil;
021    import com.liferay.portal.kernel.util.Validator;
022    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
023    import com.liferay.portal.model.Group;
024    import com.liferay.portal.model.Layout;
025    import com.liferay.portal.model.LayoutConstants;
026    import com.liferay.portal.model.LayoutSet;
027    import com.liferay.portal.model.UserGroup;
028    import com.liferay.portal.model.impl.VirtualLayout;
029    import com.liferay.portal.security.permission.PermissionChecker;
030    import com.liferay.portal.security.permission.PermissionThreadLocal;
031    import com.liferay.portal.service.GroupLocalServiceUtil;
032    import com.liferay.portal.service.LayoutLocalServiceUtil;
033    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
034    import com.liferay.portal.service.UserGroupLocalServiceUtil;
035    import com.liferay.portal.util.PropsValues;
036    import com.liferay.portlet.sites.util.SitesUtil;
037    
038    import java.lang.reflect.Method;
039    
040    import java.util.Arrays;
041    import java.util.List;
042    
043    import org.aopalliance.intercept.MethodInterceptor;
044    import org.aopalliance.intercept.MethodInvocation;
045    
046    import org.springframework.core.annotation.Order;
047    
048    /**
049     * @author Raymond Augé
050     * @author Jorge Ferrer
051     */
052    @Order(2)
053    public class LayoutLocalServiceVirtualLayoutsAdvice
054            implements MethodInterceptor {
055    
056            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
057                    PermissionChecker permissionChecker =
058                            PermissionThreadLocal.getPermissionChecker();
059    
060                    if ((permissionChecker == null) ||
061                            MergeLayoutPrototypesThreadLocal.isInProgress()) {
062    
063                            return methodInvocation.proceed();
064                    }
065    
066                    Method method = methodInvocation.getMethod();
067    
068                    String methodName = method.getName();
069    
070                    Object[] arguments = methodInvocation.getArguments();
071    
072                    Class<?>[] parameterTypes = method.getParameterTypes();
073    
074                    boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
075    
076                    if (methodName.equals("getLayout") &&
077                            (Arrays.equals(parameterTypes, _TYPES_L) ||
078                             Arrays.equals(parameterTypes, _TYPES_L_B_L))) {
079    
080                            Layout layout = (Layout)methodInvocation.proceed();
081    
082                            if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
083                                    Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
084    
085                                    return layout;
086                            }
087    
088                            Group group = layout.getGroup();
089                            LayoutSet layoutSet = layout.getLayoutSet();
090    
091                            try {
092                                    MergeLayoutPrototypesThreadLocal.setInProgress(true);
093                                    WorkflowThreadLocal.setEnabled(false);
094    
095                                    SitesUtil.mergeLayoutProtypeLayout(group, layout);
096    
097                                    if (Validator.isNotNull(
098                                                    layout.getSourcePrototypeLayoutUuid())) {
099    
100                                            SitesUtil.mergeLayoutSetProtypeLayouts(group, layoutSet);
101                                    }
102                            }
103                            finally {
104                                    MergeLayoutPrototypesThreadLocal.setInProgress(false);
105                                    WorkflowThreadLocal.setEnabled(workflowEnabled);
106                            }
107                    }
108                    else if (methodName.equals("getLayouts") &&
109                                     (Arrays.equals(parameterTypes, _TYPES_L_B_L) ||
110                                      Arrays.equals(parameterTypes, _TYPES_L_B_L_B_I_I))) {
111    
112                            long groupId = (Long)arguments[0];
113                            boolean privateLayout = (Boolean)arguments[1];
114                            long parentLayoutId = (Long)arguments[2];
115    
116                            try {
117                                    Group group = GroupLocalServiceUtil.getGroup(groupId);
118    
119                                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
120                                            groupId, privateLayout);
121    
122                                    try {
123                                            MergeLayoutPrototypesThreadLocal.setInProgress(true);
124                                            WorkflowThreadLocal.setEnabled(false);
125    
126                                            SitesUtil.mergeLayoutSetProtypeLayouts(group, layoutSet);
127                                    }
128                                    finally {
129                                            MergeLayoutPrototypesThreadLocal.setInProgress(false);
130                                            WorkflowThreadLocal.setEnabled(workflowEnabled);
131                                    }
132    
133                                    if (!PropsValues.
134                                                    USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE &&
135                                            group.isUser() &&
136                                            (parentLayoutId ==
137                                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
138    
139                                            Object returnValue = methodInvocation.proceed();
140    
141                                            return addUserGroupLayouts(
142                                                    group, layoutSet, (List<Layout>)returnValue);
143                                    }
144                            }
145                            catch (Exception e) {
146                                    _log.error(e, e);
147    
148                                    throw e;
149                            }
150                    }
151    
152                    return methodInvocation.proceed();
153            }
154    
155            protected List<Layout> addUserGroupLayouts(
156                            Group group, LayoutSet layoutSet, List<Layout> layouts)
157                    throws Exception {
158    
159                    layouts = ListUtil.copy(layouts);
160    
161                    List<UserGroup> userUserGroups =
162                            UserGroupLocalServiceUtil.getUserUserGroups(group.getClassPK());
163    
164                    for (UserGroup userGroup : userUserGroups) {
165                            Group userGroupGroup = userGroup.getGroup();
166    
167                            List<Layout> userGroupLayouts = LayoutLocalServiceUtil.getLayouts(
168                                    userGroupGroup.getGroupId(), layoutSet.isPrivateLayout());
169    
170                            for (Layout userGroupLayout : userGroupLayouts) {
171                                    Layout virtualLayout = new VirtualLayout(
172                                            userGroupLayout, group);
173    
174                                    layouts.add(virtualLayout);
175                            }
176                    }
177    
178                    return layouts;
179            }
180    
181            private static final Class<?>[] _TYPES_L = {Long.TYPE};
182    
183            private static final Class<?>[] _TYPES_L_B_L = {
184                    Long.TYPE, Boolean.TYPE, Long.TYPE
185            };
186    
187            private static final Class<?>[] _TYPES_L_B_L_B_I_I = {
188                    Long.TYPE, Boolean.TYPE, Long.TYPE, Boolean.TYPE, Integer.TYPE,
189                    Integer.TYPE
190            };
191    
192            private static Log _log = LogFactoryUtil.getLog(
193                    LayoutLocalServiceVirtualLayoutsAdvice.class);
194    
195    }