001
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.AutoResetThreadLocal;
021 import com.liferay.portal.kernel.util.ListUtil;
022 import com.liferay.portal.kernel.util.Validator;
023 import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
024 import com.liferay.portal.model.Group;
025 import com.liferay.portal.model.GroupConstants;
026 import com.liferay.portal.model.Layout;
027 import com.liferay.portal.model.LayoutConstants;
028 import com.liferay.portal.model.LayoutSet;
029 import com.liferay.portal.model.UserGroup;
030 import com.liferay.portal.model.impl.VirtualLayout;
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.ArrayList;
041 import java.util.Arrays;
042 import java.util.List;
043
044 import org.aopalliance.intercept.MethodInterceptor;
045 import org.aopalliance.intercept.MethodInvocation;
046
047 import org.springframework.core.annotation.Order;
048
049
053 @Order(2)
054 public class LayoutLocalServiceVirtualLayoutsAdvice
055 implements MethodInterceptor {
056
057 @Override
058 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
059 if (MergeLayoutPrototypesThreadLocal.isInProgress()) {
060 return methodInvocation.proceed();
061 }
062
063 Method method = methodInvocation.getMethod();
064
065 String methodName = method.getName();
066
067 Object[] arguments = methodInvocation.getArguments();
068
069 Class<?>[] parameterTypes = method.getParameterTypes();
070
071 if (MergeLayoutPrototypesThreadLocal.isMergeComplete(
072 methodName, arguments, parameterTypes)) {
073
074 return methodInvocation.proceed();
075 }
076
077 boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
078
079 if (methodName.equals("getLayout") &&
080 (Arrays.equals(parameterTypes, _TYPES_L) ||
081 Arrays.equals(parameterTypes, _TYPES_L_B_L))) {
082
083 Layout layout = (Layout)methodInvocation.proceed();
084
085 if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
086 Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
087
088 return layout;
089 }
090
091 Group group = layout.getGroup();
092 LayoutSet layoutSet = layout.getLayoutSet();
093
094 try {
095 MergeLayoutPrototypesThreadLocal.setInProgress(true);
096 WorkflowThreadLocal.setEnabled(false);
097
098 SitesUtil.mergeLayoutPrototypeLayout(group, layout);
099
100 if (Validator.isNotNull(
101 layout.getSourcePrototypeLayoutUuid())) {
102
103 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
104 }
105 }
106 finally {
107 MergeLayoutPrototypesThreadLocal.setMergeComplete(
108 methodName, arguments, parameterTypes);
109 WorkflowThreadLocal.setEnabled(workflowEnabled);
110 }
111 }
112 else if (methodName.equals("getLayouts") &&
113 (Arrays.equals(parameterTypes, _TYPES_L_B_L) ||
114 Arrays.equals(parameterTypes, _TYPES_L_B_L_B_I_I))) {
115
116 long groupId = (Long)arguments[0];
117 boolean privateLayout = (Boolean)arguments[1];
118 long parentLayoutId = (Long)arguments[2];
119
120 try {
121 Group group = GroupLocalServiceUtil.getGroup(groupId);
122
123 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
124 groupId, privateLayout);
125
126 mergeLayoutSetPrototypeLayouts(
127 methodName, arguments, parameterTypes, group, layoutSet,
128 privateLayout, workflowEnabled);
129
130 List<Layout> layouts = (List<Layout>)methodInvocation.proceed();
131
132 if (PropsValues.
133 USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
134
135 return layouts;
136 }
137
138 if (group.isUser()) {
139 _virtualLayoutTargetGroupId.set(group.getGroupId());
140
141 if (parentLayoutId ==
142 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
143
144 return addUserGroupLayouts(
145 group, layoutSet, layouts, parentLayoutId);
146 }
147 else {
148 return addChildUserGroupLayouts(group, layouts);
149 }
150 }
151 else if (group.isUserGroup() &&
152 (parentLayoutId !=
153 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
154
155 long targetGroupId = _virtualLayoutTargetGroupId.get();
156
157 if (targetGroupId != GroupConstants.DEFAULT_LIVE_GROUP_ID) {
158 Group targetGroup = GroupLocalServiceUtil.getGroup(
159 targetGroupId);
160
161 return addChildUserGroupLayouts(targetGroup, layouts);
162 }
163 }
164
165 return layouts;
166 }
167 catch (Exception e) {
168 _log.error(e, e);
169
170 throw e;
171 }
172 }
173
174 return methodInvocation.proceed();
175 }
176
177 protected List<Layout> addChildUserGroupLayouts(
178 Group group, List<Layout> layouts)
179 throws Exception {
180
181 layouts = ListUtil.copy(layouts);
182
183 List<Layout> childLayouts = new ArrayList<Layout>();
184
185 for (Layout layout : layouts) {
186 Layout childLayout = layout;
187
188 Group layoutGroup = layout.getGroup();
189
190 if (layoutGroup.isUserGroup()) {
191 childLayout = new VirtualLayout(layout, group);
192 }
193
194 childLayouts.add(childLayout);
195 }
196
197 return childLayouts;
198 }
199
200 protected List<Layout> addUserGroupLayouts(
201 Group group, LayoutSet layoutSet, List<Layout> layouts,
202 long parentLayoutId)
203 throws Exception {
204
205 layouts = ListUtil.copy(layouts);
206
207 List<UserGroup> userUserGroups =
208 UserGroupLocalServiceUtil.getUserUserGroups(group.getClassPK());
209
210 for (UserGroup userGroup : userUserGroups) {
211 Group userGroupGroup = userGroup.getGroup();
212
213 List<Layout> userGroupLayouts = LayoutLocalServiceUtil.getLayouts(
214 userGroupGroup.getGroupId(), layoutSet.isPrivateLayout(),
215 parentLayoutId);
216
217 for (Layout userGroupLayout : userGroupLayouts) {
218 Layout virtualLayout = new VirtualLayout(
219 userGroupLayout, group);
220
221 layouts.add(virtualLayout);
222 }
223 }
224
225 return layouts;
226 }
227
228 protected void mergeLayoutSetPrototypeLayouts(
229 String methodName, Object[] arguments, Class<?>[] parameterTypes,
230 Group group, LayoutSet layoutSet, boolean privateLayout,
231 boolean workflowEnabled) {
232
233 try {
234 if (!SitesUtil.isLayoutSetMergeable(group, layoutSet)) {
235 return;
236 }
237
238 MergeLayoutPrototypesThreadLocal.setInProgress(true);
239 WorkflowThreadLocal.setEnabled(false);
240
241 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
242 }
243 catch (Exception e) {
244 if (_log.isWarnEnabled()) {
245 _log.warn("Unable to merge layouts for site template", e);
246 }
247 }
248 finally {
249 MergeLayoutPrototypesThreadLocal.setMergeComplete(
250 methodName, arguments, parameterTypes);
251 WorkflowThreadLocal.setEnabled(workflowEnabled);
252 }
253 }
254
255 private static final Class<?>[] _TYPES_L = {Long.TYPE};
256
257 private static final Class<?>[] _TYPES_L_B_L = {
258 Long.TYPE, Boolean.TYPE, Long.TYPE
259 };
260
261 private static final Class<?>[] _TYPES_L_B_L_B_I_I = {
262 Long.TYPE, Boolean.TYPE, Long.TYPE, Boolean.TYPE, Integer.TYPE,
263 Integer.TYPE
264 };
265
266 private static Log _log = LogFactoryUtil.getLog(
267 LayoutLocalServiceVirtualLayoutsAdvice.class);
268
269 private static ThreadLocal<Long> _virtualLayoutTargetGroupId =
270 new AutoResetThreadLocal<Long>(
271 LayoutLocalServiceVirtualLayoutsAdvice.class +
272 "._virtualLayoutTargetGroupId",
273 GroupConstants.DEFAULT_LIVE_GROUP_ID);
274
275 }