001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.kernel.dao.orm.DynamicQuery;
018 import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
019 import com.liferay.portal.kernel.dao.orm.Property;
020 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021 import com.liferay.portal.kernel.exception.SystemException;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.staging.MergeLayoutPrototypesThreadLocal;
025 import com.liferay.portal.kernel.util.AutoResetThreadLocal;
026 import com.liferay.portal.kernel.util.ListUtil;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
029 import com.liferay.portal.model.Group;
030 import com.liferay.portal.model.GroupConstants;
031 import com.liferay.portal.model.Layout;
032 import com.liferay.portal.model.LayoutConstants;
033 import com.liferay.portal.model.LayoutSet;
034 import com.liferay.portal.model.UserGroup;
035 import com.liferay.portal.model.impl.VirtualLayout;
036 import com.liferay.portal.service.GroupLocalServiceUtil;
037 import com.liferay.portal.service.LayoutLocalServiceUtil;
038 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
039 import com.liferay.portal.service.UserGroupLocalServiceUtil;
040 import com.liferay.portal.util.PropsValues;
041 import com.liferay.portlet.sites.util.SitesUtil;
042
043 import java.lang.reflect.Method;
044
045 import java.util.ArrayList;
046 import java.util.Arrays;
047 import java.util.List;
048
049 import org.aopalliance.intercept.MethodInterceptor;
050 import org.aopalliance.intercept.MethodInvocation;
051
052 import org.springframework.core.annotation.Order;
053
054
058 @Order(2)
059 public class LayoutLocalServiceVirtualLayoutsAdvice
060 implements MethodInterceptor {
061
062 @Override
063 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
064 if (MergeLayoutPrototypesThreadLocal.isInProgress()) {
065 return methodInvocation.proceed();
066 }
067
068 Method method = methodInvocation.getMethod();
069
070 String methodName = method.getName();
071 Class<?>[] parameterTypes = method.getParameterTypes();
072
073 Object[] arguments = methodInvocation.getArguments();
074
075 boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
076
077 if (methodName.equals("getLayout") &&
078 (Arrays.equals(parameterTypes, _TYPES_L) ||
079 Arrays.equals(parameterTypes, _TYPES_L_B_L))) {
080
081 Layout layout = (Layout)methodInvocation.proceed();
082
083 Group group = layout.getGroup();
084
085 if (isMergeComplete(method, arguments, group)) {
086 return layout;
087 }
088
089 if (Validator.isNull(layout.getLayoutPrototypeUuid()) &&
090 Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
091
092 return layout;
093 }
094
095 LayoutSet layoutSet = layout.getLayoutSet();
096
097 try {
098 MergeLayoutPrototypesThreadLocal.setInProgress(true);
099 WorkflowThreadLocal.setEnabled(false);
100
101 SitesUtil.mergeLayoutPrototypeLayout(group, layout);
102
103 if (Validator.isNotNull(
104 layout.getSourcePrototypeLayoutUuid())) {
105
106 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
107 }
108 }
109 finally {
110 MergeLayoutPrototypesThreadLocal.setMergeComplete(
111 method, arguments);
112 WorkflowThreadLocal.setEnabled(workflowEnabled);
113 }
114 }
115 else if (methodName.equals("getLayouts") &&
116 (Arrays.equals(parameterTypes, _TYPES_L_B_L) ||
117 Arrays.equals(parameterTypes, _TYPES_L_B_L_B_I_I))) {
118
119 long groupId = (Long)arguments[0];
120
121 Group group = GroupLocalServiceUtil.getGroup(groupId);
122
123 if (isMergeComplete(method, arguments, group)) {
124 return methodInvocation.proceed();
125 }
126
127 boolean privateLayout = (Boolean)arguments[1];
128 long parentLayoutId = (Long)arguments[2];
129
130 try {
131 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
132 groupId, privateLayout);
133
134 mergeLayoutSetPrototypeLayouts(
135 method, arguments, group, layoutSet, privateLayout,
136 workflowEnabled);
137
138 List<Layout> layouts = (List<Layout>)methodInvocation.proceed();
139
140 if (PropsValues.
141 USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
142
143 return layouts;
144 }
145
146 if (group.isUser()) {
147 _virtualLayoutTargetGroupId.set(group.getGroupId());
148
149 if (parentLayoutId ==
150 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
151
152 return addUserGroupLayouts(
153 group, layoutSet, layouts, parentLayoutId);
154 }
155 else {
156 return addChildUserGroupLayouts(group, layouts);
157 }
158 }
159 else if (group.isUserGroup() &&
160 (parentLayoutId !=
161 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
162
163 long targetGroupId = _virtualLayoutTargetGroupId.get();
164
165 if (targetGroupId != GroupConstants.DEFAULT_LIVE_GROUP_ID) {
166 Group targetGroup = GroupLocalServiceUtil.getGroup(
167 targetGroupId);
168
169 return addChildUserGroupLayouts(targetGroup, layouts);
170 }
171 }
172
173 return layouts;
174 }
175 catch (Exception e) {
176 _log.error(e, e);
177
178 throw e;
179 }
180 }
181
182 return methodInvocation.proceed();
183 }
184
185 protected List<Layout> addChildUserGroupLayouts(
186 Group group, List<Layout> layouts)
187 throws Exception {
188
189 layouts = ListUtil.copy(layouts);
190
191 List<Layout> childLayouts = new ArrayList<Layout>();
192
193 for (Layout layout : layouts) {
194 Layout childLayout = layout;
195
196 Group layoutGroup = layout.getGroup();
197
198 if (layoutGroup.isUserGroup()) {
199 childLayout = new VirtualLayout(layout, group);
200 }
201
202 childLayouts.add(childLayout);
203 }
204
205 return childLayouts;
206 }
207
208 protected List<Layout> addUserGroupLayouts(
209 Group group, LayoutSet layoutSet, List<Layout> layouts,
210 long parentLayoutId)
211 throws Exception {
212
213 layouts = ListUtil.copy(layouts);
214
215 List<UserGroup> userUserGroups =
216 UserGroupLocalServiceUtil.getUserUserGroups(group.getClassPK());
217
218 for (UserGroup userGroup : userUserGroups) {
219 Group userGroupGroup = userGroup.getGroup();
220
221 List<Layout> userGroupLayouts = LayoutLocalServiceUtil.getLayouts(
222 userGroupGroup.getGroupId(), layoutSet.isPrivateLayout(),
223 parentLayoutId);
224
225 for (Layout userGroupLayout : userGroupLayouts) {
226 Layout virtualLayout = new VirtualLayout(
227 userGroupLayout, group);
228
229 layouts.add(virtualLayout);
230 }
231 }
232
233 return layouts;
234 }
235
236 protected List<Layout> getPrototypeLinkedLayouts(
237 long groupId, boolean privateLayout)
238 throws SystemException {
239
240 Class<?> clazz = getClass();
241
242 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
243 Layout.class, clazz.getClassLoader());
244
245 Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
246
247 dynamicQuery.add(groupIdProperty.eq(groupId));
248
249 Property layoutPrototypeUuidProperty = PropertyFactoryUtil.forName(
250 "layoutPrototypeUuid");
251
252 dynamicQuery.add(layoutPrototypeUuidProperty.isNotNull());
253
254 Property privateLayoutProperty = PropertyFactoryUtil.forName(
255 "privateLayout");
256
257 dynamicQuery.add(privateLayoutProperty.eq(privateLayout));
258
259 Property sourcePrototypeLayoutUuidProperty =
260 PropertyFactoryUtil.forName("sourcePrototypeLayoutUuid");
261
262 dynamicQuery.add(sourcePrototypeLayoutUuidProperty.isNotNull());
263
264 return LayoutLocalServiceUtil.dynamicQuery(dynamicQuery);
265 }
266
267 protected boolean isMergeComplete(
268 Method method, Object[] arguments, Group group) {
269
270 if (MergeLayoutPrototypesThreadLocal.isMergeComplete(
271 method, arguments) &&
272 (!group.isUser() ||
273 PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE)) {
274
275 return true;
276 }
277 else {
278 return false;
279 }
280 }
281
282 protected void mergeLayoutSetPrototypeLayouts(
283 Method method, Object[] arguments, Group group, LayoutSet layoutSet,
284 boolean privateLayout, boolean workflowEnabled) {
285
286 try {
287 if (!SitesUtil.isLayoutSetMergeable(group, layoutSet)) {
288 return;
289 }
290
291 MergeLayoutPrototypesThreadLocal.setInProgress(true);
292 WorkflowThreadLocal.setEnabled(false);
293
294 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
295 }
296 catch (Exception e) {
297 if (_log.isWarnEnabled()) {
298 _log.warn("Unable to merge layouts for site template", e);
299 }
300 }
301 finally {
302 MergeLayoutPrototypesThreadLocal.setMergeComplete(
303 method, arguments);
304 WorkflowThreadLocal.setEnabled(workflowEnabled);
305 }
306 }
307
308 private static final Class<?>[] _TYPES_L = {Long.TYPE};
309
310 private static final Class<?>[] _TYPES_L_B_L = {
311 Long.TYPE, Boolean.TYPE, Long.TYPE
312 };
313
314 private static final Class<?>[] _TYPES_L_B_L_B_I_I = {
315 Long.TYPE, Boolean.TYPE, Long.TYPE, Boolean.TYPE, Integer.TYPE,
316 Integer.TYPE
317 };
318
319 private static Log _log = LogFactoryUtil.getLog(
320 LayoutLocalServiceVirtualLayoutsAdvice.class);
321
322 private static ThreadLocal<Long> _virtualLayoutTargetGroupId =
323 new AutoResetThreadLocal<Long>(
324 LayoutLocalServiceVirtualLayoutsAdvice.class +
325 "._virtualLayoutTargetGroupId",
326 GroupConstants.DEFAULT_LIVE_GROUP_ID);
327
328 }