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
072 Object[] arguments = methodInvocation.getArguments();
073
074 Class<?>[] parameterTypes = method.getParameterTypes();
075
076 if (MergeLayoutPrototypesThreadLocal.isMergeComplete(
077 method, arguments)) {
078
079 return methodInvocation.proceed();
080 }
081
082 boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
083
084 if (methodName.equals("getLayout") &&
085 (Arrays.equals(parameterTypes, _TYPES_L) ||
086 Arrays.equals(parameterTypes, _TYPES_L_B_L))) {
087
088 Layout layout = (Layout)methodInvocation.proceed();
089
090 if ((Validator.isNull(layout.getLayoutPrototypeUuid()) &&
091 Validator.isNull(layout.getSourcePrototypeLayoutUuid())) ||
092 !layout.getLayoutPrototypeLinkEnabled()) {
093
094 return layout;
095 }
096
097 Group group = layout.getGroup();
098 LayoutSet layoutSet = layout.getLayoutSet();
099
100 try {
101 MergeLayoutPrototypesThreadLocal.setInProgress(true);
102 WorkflowThreadLocal.setEnabled(false);
103
104 SitesUtil.mergeLayoutPrototypeLayout(group, layout);
105
106 if (Validator.isNotNull(
107 layout.getSourcePrototypeLayoutUuid())) {
108
109 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
110 }
111 }
112 finally {
113 MergeLayoutPrototypesThreadLocal.setMergeComplete(
114 method, arguments);
115 WorkflowThreadLocal.setEnabled(workflowEnabled);
116 }
117 }
118 else if (methodName.equals("getLayouts") &&
119 (Arrays.equals(parameterTypes, _TYPES_L_B_L) ||
120 Arrays.equals(parameterTypes, _TYPES_L_B_L_B_I_I))) {
121
122 long groupId = (Long)arguments[0];
123 boolean privateLayout = (Boolean)arguments[1];
124 long parentLayoutId = (Long)arguments[2];
125
126 try {
127 Group group = GroupLocalServiceUtil.getGroup(groupId);
128
129 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
130 groupId, privateLayout);
131
132 mergeLayoutSetPrototypeLayouts(
133 method, arguments, group, layoutSet, privateLayout,
134 workflowEnabled);
135
136 List<Layout> layouts = (List<Layout>)methodInvocation.proceed();
137
138 if (PropsValues.
139 USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE) {
140
141 return layouts;
142 }
143
144 if (group.isUser()) {
145 _virtualLayoutTargetGroupId.set(group.getGroupId());
146
147 if (parentLayoutId ==
148 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
149
150 return addUserGroupLayouts(
151 group, layoutSet, layouts, parentLayoutId);
152 }
153 else {
154 return addChildUserGroupLayouts(group, layouts);
155 }
156 }
157 else if (group.isUserGroup() &&
158 (parentLayoutId !=
159 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)) {
160
161 long targetGroupId = _virtualLayoutTargetGroupId.get();
162
163 if (targetGroupId != GroupConstants.DEFAULT_LIVE_GROUP_ID) {
164 Group targetGroup = GroupLocalServiceUtil.getGroup(
165 targetGroupId);
166
167 return addChildUserGroupLayouts(targetGroup, layouts);
168 }
169 }
170
171 return layouts;
172 }
173 catch (Exception e) {
174 _log.error(e, e);
175
176 throw e;
177 }
178 }
179
180 return methodInvocation.proceed();
181 }
182
183 protected List<Layout> addChildUserGroupLayouts(
184 Group group, List<Layout> layouts)
185 throws Exception {
186
187 layouts = ListUtil.copy(layouts);
188
189 List<Layout> childLayouts = new ArrayList<Layout>();
190
191 for (Layout layout : layouts) {
192 Layout childLayout = layout;
193
194 Group layoutGroup = layout.getGroup();
195
196 if (layoutGroup.isUserGroup()) {
197 childLayout = new VirtualLayout(layout, group);
198 }
199
200 childLayouts.add(childLayout);
201 }
202
203 return childLayouts;
204 }
205
206 protected List<Layout> addUserGroupLayouts(
207 Group group, LayoutSet layoutSet, List<Layout> layouts,
208 long parentLayoutId)
209 throws Exception {
210
211 layouts = ListUtil.copy(layouts);
212
213 List<UserGroup> userUserGroups =
214 UserGroupLocalServiceUtil.getUserUserGroups(group.getClassPK());
215
216 for (UserGroup userGroup : userUserGroups) {
217 Group userGroupGroup = userGroup.getGroup();
218
219 List<Layout> userGroupLayouts = LayoutLocalServiceUtil.getLayouts(
220 userGroupGroup.getGroupId(), layoutSet.isPrivateLayout(),
221 parentLayoutId);
222
223 for (Layout userGroupLayout : userGroupLayouts) {
224 Layout virtualLayout = new VirtualLayout(
225 userGroupLayout, group);
226
227 layouts.add(virtualLayout);
228 }
229 }
230
231 return layouts;
232 }
233
234 protected List<Layout> getPrototypeLinkedLayouts(
235 long groupId, boolean privateLayout)
236 throws SystemException {
237
238 Class<?> clazz = getClass();
239
240 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
241 Layout.class, clazz.getClassLoader());
242
243 Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
244
245 dynamicQuery.add(groupIdProperty.eq(groupId));
246
247 Property layoutPrototypeUuidProperty = PropertyFactoryUtil.forName(
248 "layoutPrototypeUuid");
249
250 dynamicQuery.add(layoutPrototypeUuidProperty.isNotNull());
251
252 Property privateLayoutProperty = PropertyFactoryUtil.forName(
253 "privateLayout");
254
255 dynamicQuery.add(privateLayoutProperty.eq(privateLayout));
256
257 Property sourcePrototypeLayoutUuidProperty =
258 PropertyFactoryUtil.forName("sourcePrototypeLayoutUuid");
259
260 dynamicQuery.add(sourcePrototypeLayoutUuidProperty.isNotNull());
261
262 return LayoutLocalServiceUtil.dynamicQuery(dynamicQuery);
263 }
264
265 protected void mergeLayoutSetPrototypeLayouts(
266 Method method, Object[] arguments, Group group, LayoutSet layoutSet,
267 boolean privateLayout, boolean workflowEnabled) {
268
269 try {
270 if (!SitesUtil.isLayoutSetMergeable(group, layoutSet)) {
271 return;
272 }
273
274 MergeLayoutPrototypesThreadLocal.setInProgress(true);
275 WorkflowThreadLocal.setEnabled(false);
276
277 SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
278 }
279 catch (Exception e) {
280 if (_log.isWarnEnabled()) {
281 _log.warn("Unable to merge layouts for site template", e);
282 }
283 }
284 finally {
285 MergeLayoutPrototypesThreadLocal.setMergeComplete(
286 method, arguments);
287 WorkflowThreadLocal.setEnabled(workflowEnabled);
288 }
289 }
290
291 private static final Class<?>[] _TYPES_L = {Long.TYPE};
292
293 private static final Class<?>[] _TYPES_L_B_L = {
294 Long.TYPE, Boolean.TYPE, Long.TYPE
295 };
296
297 private static final Class<?>[] _TYPES_L_B_L_B_I_I = {
298 Long.TYPE, Boolean.TYPE, Long.TYPE, Boolean.TYPE, Integer.TYPE,
299 Integer.TYPE
300 };
301
302 private static Log _log = LogFactoryUtil.getLog(
303 LayoutLocalServiceVirtualLayoutsAdvice.class);
304
305 private static ThreadLocal<Long> _virtualLayoutTargetGroupId =
306 new AutoResetThreadLocal<Long>(
307 LayoutLocalServiceVirtualLayoutsAdvice.class +
308 "._virtualLayoutTargetGroupId",
309 GroupConstants.DEFAULT_LIVE_GROUP_ID);
310
311 }