001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.kernel.bean.BeanReference;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.staging.LayoutStagingUtil;
024 import com.liferay.portal.kernel.staging.MergeLayoutPrototypesThreadLocal;
025 import com.liferay.portal.kernel.staging.StagingUtil;
026 import com.liferay.portal.kernel.util.ArrayUtil;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.LocaleUtil;
029 import com.liferay.portal.kernel.util.ParamUtil;
030 import com.liferay.portal.kernel.util.ProxyUtil;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.workflow.WorkflowConstants;
033 import com.liferay.portal.model.Layout;
034 import com.liferay.portal.model.LayoutRevision;
035 import com.liferay.portal.model.LayoutSet;
036 import com.liferay.portal.model.LayoutStagingHandler;
037 import com.liferay.portal.model.User;
038 import com.liferay.portal.security.auth.PrincipalThreadLocal;
039 import com.liferay.portal.service.ImageLocalServiceUtil;
040 import com.liferay.portal.service.LayoutLocalService;
041 import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
042 import com.liferay.portal.service.ServiceContext;
043 import com.liferay.portal.service.ServiceContextThreadLocal;
044 import com.liferay.portal.service.UserLocalServiceUtil;
045 import com.liferay.portal.service.persistence.LayoutRevisionUtil;
046 import com.liferay.portal.service.persistence.LayoutUtil;
047 import com.liferay.portal.staging.ProxiedLayoutsThreadLocal;
048 import com.liferay.portal.staging.StagingAdvicesThreadLocal;
049 import com.liferay.portal.util.ClassLoaderUtil;
050 import com.liferay.portlet.expando.model.ExpandoBridge;
051
052 import java.lang.reflect.InvocationTargetException;
053 import java.lang.reflect.Method;
054
055 import java.util.ArrayList;
056 import java.util.HashSet;
057 import java.util.List;
058 import java.util.Locale;
059 import java.util.Map;
060 import java.util.Set;
061
062 import org.aopalliance.intercept.MethodInterceptor;
063 import org.aopalliance.intercept.MethodInvocation;
064
065 import org.springframework.core.annotation.Order;
066
067
071 @Order(1)
072 public class LayoutLocalServiceStagingAdvice implements MethodInterceptor {
073
074 public LayoutLocalServiceStagingAdvice() {
075 if (_log.isDebugEnabled()) {
076 _log.debug("Instantiating " + hashCode());
077 }
078 }
079
080 public void deleteLayout(
081 LayoutLocalService layoutLocalService, Layout layout,
082 boolean updateLayoutSet, ServiceContext serviceContext)
083 throws PortalException, SystemException {
084
085 long layoutSetBranchId = ParamUtil.getLong(
086 serviceContext, "layoutSetBranchId");
087
088 if (layoutSetBranchId > 0) {
089 LayoutRevisionLocalServiceUtil.deleteLayoutRevisions(
090 layoutSetBranchId, layout.getPlid());
091
092 List<LayoutRevision> notIncompleteLayoutRevisions =
093 LayoutRevisionUtil.findByP_NotS(
094 layout.getPlid(), WorkflowConstants.STATUS_INCOMPLETE);
095
096 if (notIncompleteLayoutRevisions.isEmpty()) {
097 LayoutRevisionLocalServiceUtil.deleteLayoutLayoutRevisions(
098 layout.getPlid());
099
100 layoutLocalService.deleteLayout(
101 layout, updateLayoutSet, serviceContext);
102 }
103 }
104 else {
105 layoutLocalService.deleteLayout(
106 layout, updateLayoutSet, serviceContext);
107 }
108 }
109
110 public void deleteLayout(
111 LayoutLocalService layoutLocalService, long groupId,
112 boolean privateLayout, long layoutId, ServiceContext serviceContext)
113 throws PortalException, SystemException {
114
115 Layout layout = layoutLocalService.getLayout(
116 groupId, privateLayout, layoutId);
117
118 deleteLayout(layoutLocalService, layout, true, serviceContext);
119 }
120
121 @Override
122 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
123 if (!StagingAdvicesThreadLocal.isEnabled()) {
124 return methodInvocation.proceed();
125 }
126
127 Method method = methodInvocation.getMethod();
128
129 String methodName = method.getName();
130
131 boolean showIncomplete = false;
132
133 if (!_layoutLocalServiceStagingAdviceMethodNames.contains(methodName)) {
134 return wrapReturnValue(methodInvocation.proceed(), showIncomplete);
135 }
136
137 Object returnValue = null;
138
139 Object thisObject = methodInvocation.getThis();
140 Object[] arguments = methodInvocation.getArguments();
141
142 if (methodName.equals("deleteLayout")) {
143 if (arguments.length == 3) {
144 deleteLayout(
145 (LayoutLocalService)thisObject, (Layout)arguments[0],
146 (Boolean)arguments[1], (ServiceContext)arguments[2]);
147 }
148 else if (arguments.length == 4) {
149 deleteLayout(
150 (LayoutLocalService)thisObject, (Long)arguments[0],
151 (Boolean)arguments[1], (Long)arguments[2],
152 (ServiceContext)arguments[3]);
153 }
154 }
155 else if (methodName.equals("getLayouts")) {
156 if (arguments.length == 6) {
157 showIncomplete = (Boolean)arguments[3];
158 }
159
160 return wrapReturnValue(methodInvocation.proceed(), showIncomplete);
161 }
162 else if (methodName.equals("updateLayout") &&
163 (arguments.length == 15)) {
164
165 returnValue = updateLayout(
166 (LayoutLocalService)thisObject, (Long)arguments[0],
167 (Boolean)arguments[1], (Long)arguments[2], (Long)arguments[3],
168 (Map<Locale, String>)arguments[4],
169 (Map<Locale, String>)arguments[5],
170 (Map<Locale, String>)arguments[6],
171 (Map<Locale, String>)arguments[7],
172 (Map<Locale, String>)arguments[8], (String)arguments[9],
173 (Boolean)arguments[10], (String)arguments[11],
174 (Boolean)arguments[12], (byte[])arguments[13],
175 (ServiceContext)arguments[14]);
176 }
177 else {
178 try {
179 Class<?> clazz = getClass();
180
181 Class<?>[] parameterTypes = ArrayUtil.append(
182 new Class<?>[] {LayoutLocalService.class},
183 method.getParameterTypes());
184
185 Method layoutLocalServiceStagingAdviceMethod = clazz.getMethod(
186 methodName, parameterTypes);
187
188 arguments = ArrayUtil.append(
189 new Object[] {thisObject}, arguments);
190
191 returnValue = layoutLocalServiceStagingAdviceMethod.invoke(
192 this, arguments);
193 }
194 catch (InvocationTargetException ite) {
195 throw ite.getTargetException();
196 }
197 catch (NoSuchMethodException nsme) {
198 returnValue = methodInvocation.proceed();
199 }
200 }
201
202 returnValue = wrapReturnValue(returnValue, showIncomplete);
203
204 return returnValue;
205 }
206
207 public Layout updateLayout(
208 LayoutLocalService layoutLocalService, long groupId,
209 boolean privateLayout, long layoutId, long parentLayoutId,
210 Map<Locale, String> nameMap, Map<Locale, String> titleMap,
211 Map<Locale, String> descriptionMap, Map<Locale, String> keywordsMap,
212 Map<Locale, String> robotsMap, String type, boolean hidden,
213 String friendlyURL, Boolean iconImage, byte[] iconBytes,
214 ServiceContext serviceContext)
215 throws PortalException, SystemException {
216
217
218
219 parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
220 groupId, privateLayout, parentLayoutId);
221 String name = nameMap.get(LocaleUtil.getDefault());
222 friendlyURL = layoutLocalServiceHelper.getFriendlyURL(
223 groupId, privateLayout, layoutId, StringPool.BLANK, friendlyURL);
224
225 layoutLocalServiceHelper.validate(
226 groupId, privateLayout, layoutId, parentLayoutId, name, type,
227 hidden, friendlyURL);
228
229 layoutLocalServiceHelper.validateParentLayoutId(
230 groupId, privateLayout, layoutId, parentLayoutId);
231
232 Layout originalLayout = LayoutUtil.findByG_P_L(
233 groupId, privateLayout, layoutId);
234
235 Layout layout = wrapLayout(originalLayout);
236
237 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
238 layout);
239
240 if (layoutRevision == null) {
241 return layoutLocalService.updateLayout(
242 groupId, privateLayout, layoutId, parentLayoutId, nameMap,
243 titleMap, descriptionMap, keywordsMap, robotsMap, type, hidden,
244 friendlyURL, iconImage, iconBytes, serviceContext);
245 }
246
247 if (parentLayoutId != originalLayout.getParentLayoutId()) {
248 int priority = layoutLocalServiceHelper.getNextPriority(
249 groupId, privateLayout, parentLayoutId,
250 originalLayout.getSourcePrototypeLayoutUuid(), -1);
251
252 originalLayout.setPriority(priority);
253 }
254
255 originalLayout.setParentLayoutId(parentLayoutId);
256 layoutRevision.setNameMap(nameMap);
257 layoutRevision.setTitleMap(titleMap);
258 layoutRevision.setDescriptionMap(descriptionMap);
259 layoutRevision.setKeywordsMap(keywordsMap);
260 layoutRevision.setRobotsMap(robotsMap);
261 originalLayout.setType(type);
262 originalLayout.setHidden(hidden);
263 originalLayout.setFriendlyURL(friendlyURL);
264
265 if (iconImage != null) {
266 layoutRevision.setIconImage(iconImage.booleanValue());
267
268 if (iconImage.booleanValue()) {
269 long iconImageId = layoutRevision.getIconImageId();
270
271 if (iconImageId <= 0) {
272 iconImageId = CounterLocalServiceUtil.increment();
273
274 layoutRevision.setIconImageId(iconImageId);
275 }
276 }
277 }
278
279 boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
280 serviceContext, "layoutPrototypeLinkEnabled", true);
281
282 originalLayout.setLayoutPrototypeLinkEnabled(
283 layoutPrototypeLinkEnabled);
284
285 LayoutUtil.update(originalLayout, false);
286
287 boolean hasWorkflowTask = StagingUtil.hasWorkflowTask(
288 serviceContext.getUserId(), layoutRevision);
289
290 serviceContext.setAttribute("revisionInProgress", hasWorkflowTask);
291
292 serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
293
294 LayoutRevisionLocalServiceUtil.updateLayoutRevision(
295 serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
296 layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
297 layoutRevision.getTitle(), layoutRevision.getDescription(),
298 layoutRevision.getKeywords(), layoutRevision.getRobots(),
299 layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
300 layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
301 layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
302 layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
303 serviceContext);
304
305
306
307 if (iconImage != null) {
308 if ((iconBytes != null) && (iconBytes.length > 0)) {
309 ImageLocalServiceUtil.updateImage(
310 layoutRevision.getIconImageId(), iconBytes);
311 }
312 }
313
314
315
316 ExpandoBridge expandoBridge = originalLayout.getExpandoBridge();
317
318 expandoBridge.setAttributes(serviceContext);
319
320 return layout;
321 }
322
323 public Layout updateLayout(
324 LayoutLocalService layoutLocalService, long groupId,
325 boolean privateLayout, long layoutId, String typeSettings)
326 throws PortalException, SystemException {
327
328 Layout layout = LayoutUtil.findByG_P_L(
329 groupId, privateLayout, layoutId);
330
331 layout = wrapLayout(layout);
332
333 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
334 layout);
335
336 if (layoutRevision == null) {
337 return layoutLocalService.updateLayout(
338 groupId, privateLayout, layoutId, typeSettings);
339 }
340
341 layout.setTypeSettings(typeSettings);
342
343 ServiceContext serviceContext =
344 ServiceContextThreadLocal.getServiceContext();
345
346 boolean hasWorkflowTask = StagingUtil.hasWorkflowTask(
347 serviceContext.getUserId(), layoutRevision);
348
349 serviceContext.setAttribute("revisionInProgress", hasWorkflowTask);
350
351 if (!MergeLayoutPrototypesThreadLocal.isInProgress()) {
352 serviceContext.setWorkflowAction(
353 WorkflowConstants.ACTION_SAVE_DRAFT);
354 }
355
356 LayoutRevisionLocalServiceUtil.updateLayoutRevision(
357 serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
358 layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
359 layoutRevision.getTitle(), layoutRevision.getDescription(),
360 layoutRevision.getKeywords(), layoutRevision.getRobots(),
361 layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
362 layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
363 layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
364 layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
365 serviceContext);
366
367 return layout;
368 }
369
370 public Layout updateLookAndFeel(
371 LayoutLocalService layoutLocalService, long groupId,
372 boolean privateLayout, long layoutId, String themeId,
373 String colorSchemeId, String css, boolean wapTheme)
374 throws PortalException, SystemException {
375
376 Layout layout = LayoutUtil.findByG_P_L(
377 groupId, privateLayout, layoutId);
378
379 layout = wrapLayout(layout);
380
381 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
382 layout);
383
384 if (layoutRevision == null) {
385 return layoutLocalService.updateLookAndFeel(
386 groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
387 wapTheme);
388 }
389
390 if (wapTheme) {
391 layout.setWapThemeId(themeId);
392 layout.setWapColorSchemeId(colorSchemeId);
393 }
394 else {
395 layout.setThemeId(themeId);
396 layout.setColorSchemeId(colorSchemeId);
397 layout.setCss(css);
398 }
399
400 ServiceContext serviceContext =
401 ServiceContextThreadLocal.getServiceContext();
402
403 boolean hasWorkflowTask = StagingUtil.hasWorkflowTask(
404 serviceContext.getUserId(), layoutRevision);
405
406 serviceContext.setAttribute("revisionInProgress", hasWorkflowTask);
407
408 if (!MergeLayoutPrototypesThreadLocal.isInProgress()) {
409 serviceContext.setWorkflowAction(
410 WorkflowConstants.ACTION_SAVE_DRAFT);
411 }
412
413 LayoutRevisionLocalServiceUtil.updateLayoutRevision(
414 serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
415 layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
416 layoutRevision.getTitle(), layoutRevision.getDescription(),
417 layoutRevision.getKeywords(), layoutRevision.getRobots(),
418 layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
419 layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
420 layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
421 layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
422 serviceContext);
423
424 return layout;
425 }
426
427 public Layout updateName(
428 LayoutLocalService layoutLocalService, Layout layout, String name,
429 String languageId)
430 throws PortalException, SystemException {
431
432 layout = wrapLayout(layout);
433
434 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
435 layout);
436
437 if (layoutRevision == null) {
438 return layoutLocalService.updateName(layout, name, languageId);
439 }
440
441 layoutLocalServiceHelper.validateName(name, languageId);
442
443 layout.setName(name, LocaleUtil.fromLanguageId(languageId));
444
445 ServiceContext serviceContext =
446 ServiceContextThreadLocal.getServiceContext();
447
448 boolean hasWorkflowTask = StagingUtil.hasWorkflowTask(
449 serviceContext.getUserId(), layoutRevision);
450
451 serviceContext.setAttribute("revisionInProgress", hasWorkflowTask);
452
453 serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
454
455 LayoutRevisionLocalServiceUtil.updateLayoutRevision(
456 serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
457 layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
458 layoutRevision.getTitle(), layoutRevision.getDescription(),
459 layoutRevision.getKeywords(), layoutRevision.getRobots(),
460 layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
461 layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
462 layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
463 layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
464 serviceContext);
465
466 return layout;
467 }
468
469 protected Layout getProxiedLayout(Layout layout) {
470 Map<Layout, Object> proxiedLayouts =
471 ProxiedLayoutsThreadLocal.getProxiedLayouts();
472
473 Object proxiedLayout = proxiedLayouts.get(layout);
474
475 if (proxiedLayout != null) {
476 return (Layout)proxiedLayout;
477 }
478
479 proxiedLayout = ProxyUtil.newProxyInstance(
480 ClassLoaderUtil.getPortalClassLoader(), new Class[] {Layout.class},
481 new LayoutStagingHandler(layout));
482
483 proxiedLayouts.put(layout, proxiedLayout);
484
485 return (Layout)proxiedLayout;
486 }
487
488 protected Layout unwrapLayout(Layout layout) {
489 LayoutStagingHandler layoutStagingHandler =
490 LayoutStagingUtil.getLayoutStagingHandler(layout);
491
492 if (layoutStagingHandler == null) {
493 return layout;
494 }
495
496 return layoutStagingHandler.getLayout();
497 }
498
499 protected Layout wrapLayout(Layout layout) {
500 LayoutStagingHandler layoutStagingHandler =
501 LayoutStagingUtil.getLayoutStagingHandler(layout);
502
503 if (layoutStagingHandler != null) {
504 return layout;
505 }
506
507 if (!LayoutStagingUtil.isBranchingLayout(layout)) {
508 return layout;
509 }
510
511 return getProxiedLayout(layout);
512 }
513
514 protected List<Layout> wrapLayouts(
515 List<Layout> layouts, boolean showIncomplete) {
516
517 if (layouts.isEmpty()) {
518 return layouts;
519 }
520
521 Layout firstLayout = layouts.get(0);
522
523 Layout wrappedFirstLayout = wrapLayout(firstLayout);
524
525 if (wrappedFirstLayout == firstLayout) {
526 return layouts;
527 }
528
529 long layoutSetBranchId = 0;
530
531 if (!showIncomplete) {
532 try {
533 long userId = GetterUtil.getLong(
534 PrincipalThreadLocal.getName());
535
536 if (userId > 0) {
537 User user = UserLocalServiceUtil.getUser(userId);
538
539 LayoutSet layoutSet = firstLayout.getLayoutSet();
540
541 layoutSetBranchId = StagingUtil.getRecentLayoutSetBranchId(
542 user, layoutSet.getLayoutSetId());
543 }
544 }
545 catch (Exception e) {
546 }
547 }
548
549 List<Layout> wrappedLayouts = new ArrayList<Layout>(layouts.size());
550
551 for (int i = 0; i < layouts.size(); i++) {
552 Layout wrappedLayout = wrapLayout(layouts.get(i));
553
554 if (showIncomplete ||
555 !StagingUtil.isIncomplete(wrappedLayout, layoutSetBranchId)) {
556
557 wrappedLayouts.add(wrappedLayout);
558 }
559 }
560
561 return wrappedLayouts;
562 }
563
564 protected Object wrapReturnValue(
565 Object returnValue, boolean showIncomplete) {
566
567 if (returnValue instanceof Layout) {
568 returnValue = wrapLayout((Layout)returnValue);
569 }
570 else if (returnValue instanceof List<?>) {
571 List<?> list = (List<?>)returnValue;
572
573 if (!list.isEmpty()) {
574 Object object = list.get(0);
575
576 if (object instanceof Layout) {
577 returnValue = wrapLayouts(
578 (List<Layout>)returnValue, showIncomplete);
579 }
580
581 }
582 }
583
584 return returnValue;
585 }
586
587 @BeanReference(type = LayoutLocalServiceHelper.class)
588 protected LayoutLocalServiceHelper layoutLocalServiceHelper;
589
590 private static Log _log = LogFactoryUtil.getLog(
591 LayoutLocalServiceStagingAdvice.class);
592
593 private static Set<String> _layoutLocalServiceStagingAdviceMethodNames =
594 new HashSet<String>();
595
596 static {
597 _layoutLocalServiceStagingAdviceMethodNames.add("deleteLayout");
598 _layoutLocalServiceStagingAdviceMethodNames.add("getLayouts");
599 _layoutLocalServiceStagingAdviceMethodNames.add("updateLayout");
600 _layoutLocalServiceStagingAdviceMethodNames.add("updateLookAndFeel");
601 _layoutLocalServiceStagingAdviceMethodNames.add("updateName");
602 }
603
604 }