001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.staging.LayoutStagingUtil;
020    import com.liferay.portal.kernel.staging.StagingUtil;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.LocaleUtil;
023    import com.liferay.portal.kernel.util.ParamUtil;
024    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
025    import com.liferay.portal.kernel.util.ProxyUtil;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.workflow.WorkflowConstants;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.model.LayoutRevision;
030    import com.liferay.portal.model.LayoutSet;
031    import com.liferay.portal.model.LayoutStagingHandler;
032    import com.liferay.portal.model.User;
033    import com.liferay.portal.security.auth.PrincipalThreadLocal;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portal.service.ServiceContextThreadLocal;
036    import com.liferay.portal.service.UserLocalServiceUtil;
037    import com.liferay.portlet.expando.model.ExpandoBridge;
038    
039    import java.lang.reflect.Method;
040    
041    import java.util.ArrayList;
042    import java.util.HashSet;
043    import java.util.List;
044    import java.util.Locale;
045    import java.util.Map;
046    import java.util.Set;
047    
048    import org.aopalliance.intercept.MethodInterceptor;
049    import org.aopalliance.intercept.MethodInvocation;
050    
051    /**
052     * @author Raymond Augé
053     * @author Brian Wing Shun Chan
054     */
055    public class LayoutLocalServiceStagingAdvice
056            extends LayoutLocalServiceImpl implements MethodInterceptor {
057    
058            @Override
059            public void deleteLayout(
060                            Layout layout, boolean updateLayoutSet,
061                            ServiceContext serviceContext)
062                    throws PortalException, SystemException {
063    
064                    long layoutSetBranchId = ParamUtil.getLong(
065                            serviceContext, "layoutSetBranchId");
066    
067                    if (layoutSetBranchId > 0) {
068                            layoutRevisionLocalService.deleteLayoutRevisions(
069                                    layoutSetBranchId, layout.getPlid());
070                    }
071                    else {
072                            super.deleteLayout(layout, updateLayoutSet, serviceContext);
073                    }
074            }
075    
076            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
077                    Method method = methodInvocation.getMethod();
078    
079                    String methodName = method.getName();
080    
081                    Object[] arguments = methodInvocation.getArguments();
082    
083                    boolean showIncomplete = false;
084    
085                    if (!_layoutLocalServiceStagingAdviceMethodNames.contains(
086                                    methodName)) {
087    
088                            return wrapReturnValue(methodInvocation.proceed(), showIncomplete);
089                    }
090    
091                    Object returnValue = null;
092    
093                    if (methodName.equals("deleteLayout") && (arguments.length == 3)) {
094                            deleteLayout(
095                                    (Layout)arguments[0], (Boolean)arguments[1],
096                                    (ServiceContext)arguments[2]);
097                    }
098                    else if (methodName.equals("updateLayout") &&
099                                     (arguments.length == 16)) {
100    
101                            returnValue = updateLayout(
102                                    (Long)arguments[0], (Boolean)arguments[1], (Long)arguments[2],
103                                    (Long)arguments[3], (Map<Locale, String>)arguments[4],
104                                    (Map<Locale, String>)arguments[5],
105                                    (Map<Locale, String>)arguments[6],
106                                    (Map<Locale, String>)arguments[7],
107                                    (Map<Locale, String>)arguments[8], (String)arguments[9],
108                                    (Boolean)arguments[10], (String)arguments[11],
109                                    (Boolean)arguments[12], (byte[])arguments[13],
110                                    (Boolean)arguments[14], (ServiceContext)arguments[15]);
111                    }
112                    else if (methodName.equals("getLayouts")) {
113                            if (arguments.length == 6) {
114                                    showIncomplete = (Boolean)arguments[3];
115                            }
116    
117                            return wrapReturnValue(methodInvocation.proceed(), showIncomplete);
118                    }
119                    else {
120                            try {
121                                    Class<?> clazz = getClass();
122    
123                                    Method localMethod = clazz.getMethod(
124                                            methodName, method.getParameterTypes());
125    
126                                    returnValue = localMethod.invoke(this, arguments);
127                            }
128                            catch (NoSuchMethodException nsme) {
129                                    throw new SystemException(nsme);
130                            }
131                    }
132    
133                    returnValue = wrapReturnValue(returnValue, showIncomplete);
134    
135                    return returnValue;
136            }
137    
138            @Override
139            public Layout updateLayout(
140                            long groupId, boolean privateLayout, long layoutId,
141                            long parentLayoutId, Map<Locale, String> nameMap,
142                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
143                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
144                            String type, boolean hidden, String friendlyURL, Boolean iconImage,
145                            byte[] iconBytes, boolean locked, ServiceContext serviceContext)
146                    throws PortalException, SystemException {
147    
148                    // Layout
149    
150                    parentLayoutId = getParentLayoutId(
151                            groupId, privateLayout, parentLayoutId);
152                    String name = nameMap.get(LocaleUtil.getDefault());
153                    friendlyURL = getFriendlyURL(
154                            groupId, privateLayout, layoutId, StringPool.BLANK, friendlyURL);
155    
156                    validate(
157                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
158                            hidden, friendlyURL);
159    
160                    validateParentLayoutId(
161                            groupId, privateLayout, layoutId, parentLayoutId);
162    
163                    Layout layout = layoutPersistence.findByG_P_L(
164                            groupId, privateLayout, layoutId);
165    
166                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
167                            layout);
168    
169                    if (layoutRevision == null) {
170                            return super.updateLayout(
171                                    groupId, privateLayout, layoutId, parentLayoutId, nameMap,
172                                    titleMap, descriptionMap, keywordsMap, robotsMap, type, hidden,
173                                    friendlyURL, iconImage, iconBytes, locked, serviceContext);
174                    }
175    
176                    if (parentLayoutId != layout.getParentLayoutId()) {
177                            layout.setPriority(
178                                    getNextPriority(groupId, privateLayout, parentLayoutId));
179                    }
180    
181                    layout.setParentLayoutId(parentLayoutId);
182                    layoutRevision.setNameMap(nameMap);
183                    layoutRevision.setTitleMap(titleMap);
184                    layoutRevision.setDescriptionMap(descriptionMap);
185                    layoutRevision.setKeywordsMap(keywordsMap);
186                    layoutRevision.setRobotsMap(robotsMap);
187                    layout.setType(type);
188                    layout.setHidden(hidden);
189                    layout.setFriendlyURL(friendlyURL);
190    
191                    if (iconImage != null) {
192                            layout.setIconImage(iconImage.booleanValue());
193    
194                            if (iconImage.booleanValue()) {
195                                    long iconImageId = layout.getIconImageId();
196    
197                                    if (iconImageId <= 0) {
198                                            iconImageId = counterLocalService.increment();
199    
200                                            layout.setIconImageId(iconImageId);
201                                    }
202                            }
203                    }
204    
205                    layoutPersistence.update(layout, false);
206    
207                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
208    
209                    layoutRevisionLocalService.updateLayoutRevision(
210                            serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
211                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
212                            layoutRevision.getTitle(), layoutRevision.getDescription(),
213                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
214                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
215                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
216                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
217                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
218                            serviceContext);
219    
220                    // Icon
221    
222                    if (iconImage != null) {
223                            if ((iconBytes != null) && (iconBytes.length > 0)) {
224                                    imageLocalService.updateImage(
225                                            layout.getIconImageId(), iconBytes);
226                            }
227                    }
228    
229                    // Expando
230    
231                    ExpandoBridge expandoBridge = layout.getExpandoBridge();
232    
233                    expandoBridge.setAttributes(serviceContext);
234    
235                    return wrapLayout(layout);
236            }
237    
238            @Override
239            public Layout updateLayout(
240                            long groupId, boolean privateLayout, long layoutId,
241                            String typeSettings)
242                    throws PortalException, SystemException {
243    
244                    Layout layout = layoutPersistence.findByG_P_L(
245                            groupId, privateLayout, layoutId);
246    
247                    layout = wrapLayout(layout);
248    
249                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
250                            layout);
251    
252                    if (layoutRevision == null) {
253                            return super.updateLayout(
254                                    groupId, privateLayout, layoutId, typeSettings);
255                    }
256    
257                    layout.setTypeSettings(typeSettings);
258    
259                    ServiceContext serviceContext =
260                            ServiceContextThreadLocal.getServiceContext();
261    
262                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
263    
264                    layoutRevisionLocalService.updateLayoutRevision(
265                            serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
266                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
267                            layoutRevision.getTitle(), layoutRevision.getDescription(),
268                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
269                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
270                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
271                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
272                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
273                            serviceContext);
274    
275                    return layout;
276            }
277    
278            @Override
279            public Layout updateLookAndFeel(
280                            long groupId, boolean privateLayout, long layoutId, String themeId,
281                            String colorSchemeId, String css, boolean wapTheme)
282                    throws PortalException, SystemException {
283    
284                    Layout layout = layoutPersistence.findByG_P_L(
285                            groupId, privateLayout, layoutId);
286    
287                    layout = wrapLayout(layout);
288    
289                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
290                            layout);
291    
292                    if (layoutRevision == null) {
293                            return super.updateLookAndFeel(
294                                    groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
295                                    wapTheme);
296                    }
297    
298                    if (wapTheme) {
299                            layout.setWapThemeId(themeId);
300                            layout.setWapColorSchemeId(colorSchemeId);
301                    }
302                    else {
303                            layout.setThemeId(themeId);
304                            layout.setColorSchemeId(colorSchemeId);
305                            layout.setCss(css);
306                    }
307    
308                    ServiceContext serviceContext =
309                            ServiceContextThreadLocal.getServiceContext();
310    
311                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
312    
313                    layoutRevisionLocalService.updateLayoutRevision(
314                            serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
315                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
316                            layoutRevision.getTitle(), layoutRevision.getDescription(),
317                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
318                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
319                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
320                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
321                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
322                            serviceContext);
323    
324                    return layout;
325            }
326    
327            @Override
328            public Layout updateName(Layout layout, String name, String languageId)
329                    throws PortalException, SystemException {
330    
331                    layout = wrapLayout(layout);
332    
333                    LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
334                            layout);
335    
336                    if (layoutRevision == null) {
337                            return super.updateName(layout, name, languageId);
338                    }
339    
340                    validateName(name, languageId);
341    
342                    layout.setName(name, LocaleUtil.fromLanguageId(languageId));
343    
344                    ServiceContext serviceContext =
345                            ServiceContextThreadLocal.getServiceContext();
346    
347                    serviceContext.setWorkflowAction(WorkflowConstants.ACTION_SAVE_DRAFT);
348    
349                    layoutRevisionLocalService.updateLayoutRevision(
350                            serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(),
351                            layoutRevision.getLayoutBranchId(), layoutRevision.getName(),
352                            layoutRevision.getTitle(), layoutRevision.getDescription(),
353                            layoutRevision.getKeywords(), layoutRevision.getRobots(),
354                            layoutRevision.getTypeSettings(), layoutRevision.getIconImage(),
355                            layoutRevision.getIconImageId(), layoutRevision.getThemeId(),
356                            layoutRevision.getColorSchemeId(), layoutRevision.getWapThemeId(),
357                            layoutRevision.getWapColorSchemeId(), layoutRevision.getCss(),
358                            serviceContext);
359    
360                    return layout;
361            }
362    
363            protected Layout unwrapLayout(Layout layout) {
364                    LayoutStagingHandler layoutStagingHandler =
365                            LayoutStagingUtil.getLayoutStagingHandler(layout);
366    
367                    if (layoutStagingHandler == null) {
368                            return layout;
369                    }
370    
371                    return layoutStagingHandler.getLayout();
372            }
373    
374            protected Layout wrapLayout(Layout layout) {
375                    LayoutStagingHandler layoutStagingHandler =
376                            LayoutStagingUtil.getLayoutStagingHandler(layout);
377    
378                    if (layoutStagingHandler != null) {
379                            return layout;
380                    }
381    
382                    if (!LayoutStagingUtil.isBranchingLayout(layout)) {
383                            return layout;
384                    }
385    
386                    return (Layout)ProxyUtil.newProxyInstance(
387                            PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
388                            new LayoutStagingHandler(layout));
389            }
390    
391            protected List<Layout> wrapLayouts(
392                    List<Layout> layouts, boolean showIncomplete) {
393    
394                    if (layouts.isEmpty()) {
395                            return layouts;
396                    }
397    
398                    Layout firstLayout = layouts.get(0);
399    
400                    Layout wrappedFirstLayout = wrapLayout(firstLayout);
401    
402                    if (wrappedFirstLayout == firstLayout) {
403                            return layouts;
404                    }
405    
406                    long layoutSetBranchId = 0;
407    
408                    if (!showIncomplete) {
409                            try {
410                                    long userId = GetterUtil.getLong(
411                                            PrincipalThreadLocal.getName());
412    
413                                    if (userId > 0) {
414                                            User user = UserLocalServiceUtil.getUser(userId);
415    
416                                            LayoutSet layoutSet = firstLayout.getLayoutSet();
417    
418                                            layoutSetBranchId = StagingUtil.getRecentLayoutSetBranchId(
419                                                    user, layoutSet.getLayoutSetId());
420                                    }
421                            }
422                            catch (Exception e) {
423                            }
424                    }
425    
426                    List<Layout> wrappedLayouts = new ArrayList<Layout>(layouts.size());
427    
428                    for (int i = 0; i < layouts.size(); i++) {
429                            Layout wrappedLayout = wrapLayout(layouts.get(i));
430    
431                            if (showIncomplete ||
432                                    !StagingUtil.isIncomplete(wrappedLayout, layoutSetBranchId)) {
433    
434                                    wrappedLayouts.add(wrappedLayout);
435                            }
436                    }
437    
438                    return wrappedLayouts;
439            }
440    
441            protected Object wrapReturnValue(
442                    Object returnValue, boolean showIncomplete) {
443    
444                    if (returnValue instanceof Layout) {
445                            returnValue = wrapLayout((Layout)returnValue);
446                    }
447                    else if (returnValue instanceof List<?>) {
448                            returnValue = wrapLayouts(
449                                    (List<Layout>)returnValue, showIncomplete);
450                    }
451    
452                    return returnValue;
453            }
454    
455            private static Set<String> _layoutLocalServiceStagingAdviceMethodNames =
456                    new HashSet<String>();
457    
458            static {
459                    _layoutLocalServiceStagingAdviceMethodNames.add("deleteLayout");
460                    _layoutLocalServiceStagingAdviceMethodNames.add("getLayouts");
461                    _layoutLocalServiceStagingAdviceMethodNames.add("updateLayout");
462                    _layoutLocalServiceStagingAdviceMethodNames.add("updateLookAndFeel");
463                    _layoutLocalServiceStagingAdviceMethodNames.add("updateName");
464            }
465    
466    }