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