/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.model; import com.liferay.exportimport.kernel.staging.StagingUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.service.LayoutBranchLocalServiceUtil; import com.liferay.portal.kernel.service.LayoutRevisionLocalServiceUtil; import com.liferay.portal.kernel.service.LayoutSetBranchLocalServiceUtil; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.ServiceContextThreadLocal; import com.liferay.portal.kernel.service.UserLocalServiceUtil; import com.liferay.portal.kernel.util.LayoutTypePortletFactoryUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.PortalClassLoaderUtil; import com.liferay.portal.kernel.util.ProxyUtil; import com.liferay.portal.kernel.util.ReflectionUtil; import com.liferay.portal.kernel.workflow.WorkflowConstants; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpServletRequest; /** * @author Raymond Augé * @author Brian Wing Shun Chan */ public class LayoutStagingHandler implements InvocationHandler, Serializable { public LayoutStagingHandler(Layout layout) { this(layout, null); } public Layout getLayout() { return _layout; } public LayoutRevision getLayoutRevision() { return _layoutRevision; } @Override public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable { try { if (_layoutRevision == null) { return method.invoke(_layout, arguments); } String methodName = method.getName(); if (methodName.equals("getLayoutType")) { return _getLayoutType(); } else if (methodName.equals("getRegularURL")) { Class<?> layoutRevisionClass = _layoutRevision.getClass(); method = layoutRevisionClass.getMethod( methodName, HttpServletRequest.class); return method.invoke(_layoutRevision, arguments); } else if (methodName.equals("toEscapedModel")) { if (_layout.isEscapedModel()) { return this; } return _toEscapedModel(); } if (methodName.equals("clone")) { return _clone(); } Object bean = _layout; if (_layoutRevisionMethodNames.contains(methodName)) { try { Class<?> layoutRevisionClass = _layoutRevision.getClass(); method = layoutRevisionClass.getMethod( methodName, ReflectionUtil.getParameterTypes(arguments)); bean = _layoutRevision; } catch (NoSuchMethodException nsme) { _log.error(nsme, nsme); } } return method.invoke(bean, arguments); } catch (InvocationTargetException ite) { throw ite.getTargetException(); } } public void setLayoutRevision(LayoutRevision layoutRevision) { _layoutRevision = layoutRevision; } private LayoutStagingHandler(Layout layout, LayoutRevision layoutRevision) { _layout = layout; try { _layoutRevision = _getLayoutRevision(layout, layoutRevision); } catch (Exception e) { _log.error(e, e); throw new IllegalStateException(e); } } private Object _clone() { return ProxyUtil.newProxyInstance( PortalClassLoaderUtil.getClassLoader(), new Class<?>[] {Layout.class}, new LayoutStagingHandler(_layout, _layoutRevision)); } private LayoutRevision _getLayoutRevision( Layout layout, LayoutRevision layoutRevision) throws PortalException { if (layoutRevision != null) { return layoutRevision; } ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext(); if ((serviceContext == null) || !serviceContext.isSignedIn()) { LayoutRevision lastLayoutRevision = null; lastLayoutRevision = LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision( layout.getPlid(), true); if (lastLayoutRevision == null) { lastLayoutRevision = LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision( layout.getPlid(), false); } return lastLayoutRevision; } User user = UserLocalServiceUtil.getUser(serviceContext.getUserId()); long layoutSetBranchId = ParamUtil.getLong( serviceContext, "layoutSetBranchId"); LayoutSet layoutSet = layout.getLayoutSet(); LayoutSetBranch layoutSetBranch = LayoutSetBranchLocalServiceUtil.getUserLayoutSetBranch( serviceContext.getUserId(), layout.getGroupId(), layout.isPrivateLayout(), layoutSet.getLayoutSetId(), layoutSetBranchId); layoutSetBranchId = layoutSetBranch.getLayoutSetBranchId(); long layoutRevisionId = ParamUtil.getLong( serviceContext, "layoutRevisionId"); if (layoutRevisionId > 0) { layoutRevision = LayoutRevisionLocalServiceUtil.fetchLayoutRevision( layoutRevisionId); } if ((layoutRevisionId <= 0) || !_isBelongsToLayout(layoutRevision, layout)) { layoutRevisionId = StagingUtil.getRecentLayoutRevisionId( user, layoutSetBranchId, layout.getPlid()); layoutRevision = LayoutRevisionLocalServiceUtil.fetchLayoutRevision( layoutRevisionId); } if ((layoutRevision != null) && !layoutRevision.isInactive()) { return layoutRevision; } layoutRevision = LayoutRevisionLocalServiceUtil.fetchLatestLayoutRevision( layoutSetBranchId, layout.getPlid()); if (layoutRevision != null) { StagingUtil.setRecentLayoutRevisionId( user, layoutSetBranchId, layout.getPlid(), layoutRevision.getLayoutRevisionId()); return layoutRevision; } LayoutBranch layoutBranch = LayoutBranchLocalServiceUtil.getMasterLayoutBranch( layoutSetBranchId, layout.getPlid(), serviceContext); layoutRevision = LayoutRevisionLocalServiceUtil.addLayoutRevision( serviceContext.getUserId(), layoutSetBranchId, layoutBranch.getLayoutBranchId(), LayoutRevisionConstants.DEFAULT_PARENT_LAYOUT_REVISION_ID, false, layout.getPlid(), LayoutConstants.DEFAULT_PLID, layout.isPrivateLayout(), layout.getName(), layout.getTitle(), layout.getDescription(), layout.getKeywords(), layout.getRobots(), layout.getTypeSettings(), layout.getIconImage(), layout.getIconImageId(), layout.getThemeId(), layout.getColorSchemeId(), layout.getCss(), serviceContext); boolean explicitCreation = ParamUtil.getBoolean( serviceContext, "explicitCreation"); if (!explicitCreation) { LayoutRevisionLocalServiceUtil.updateStatus( serviceContext.getUserId(), layoutRevision.getLayoutRevisionId(), WorkflowConstants.STATUS_INCOMPLETE, serviceContext); } return layoutRevision; } private LayoutType _getLayoutType() { return LayoutTypePortletFactoryUtil.create( (Layout)ProxyUtil.newProxyInstance( PortalClassLoaderUtil.getClassLoader(), new Class<?>[] {Layout.class}, new LayoutStagingHandler(_layout, _layoutRevision))); } private boolean _isBelongsToLayout( LayoutRevision layoutRevision, Layout layout) { if (layoutRevision == null) { return false; } if (layoutRevision.getPlid() == layout.getPlid()) { return true; } return false; } private Object _toEscapedModel() { return ProxyUtil.newProxyInstance( PortalClassLoaderUtil.getClassLoader(), new Class<?>[] {Layout.class}, new LayoutStagingHandler( _layout.toEscapedModel(), _layoutRevision.toEscapedModel())); } private static final Log _log = LogFactoryUtil.getLog( LayoutStagingHandler.class); private static final Set<String> _layoutRevisionMethodNames = new HashSet<>(); static { _layoutRevisionMethodNames.add("getColorScheme"); _layoutRevisionMethodNames.add("getColorSchemeId"); _layoutRevisionMethodNames.add("getCss"); _layoutRevisionMethodNames.add("getCssText"); _layoutRevisionMethodNames.add("getDescription"); _layoutRevisionMethodNames.add("getGroupId"); _layoutRevisionMethodNames.add("getHTMLTitle"); _layoutRevisionMethodNames.add("getIconImage"); _layoutRevisionMethodNames.add("getIconImageId"); _layoutRevisionMethodNames.add("getKeywords"); _layoutRevisionMethodNames.add("getLayoutSet"); _layoutRevisionMethodNames.add("getName"); _layoutRevisionMethodNames.add("getRobots"); _layoutRevisionMethodNames.add("getTheme"); _layoutRevisionMethodNames.add("getThemeId"); _layoutRevisionMethodNames.add("getThemeSetting"); _layoutRevisionMethodNames.add("getTitle"); _layoutRevisionMethodNames.add("getTypeSettings"); _layoutRevisionMethodNames.add("getTypeSettingsProperties"); _layoutRevisionMethodNames.add("getTypeSettingsProperty"); _layoutRevisionMethodNames.add("isContentDisplayPage"); _layoutRevisionMethodNames.add("isEscapedModel"); _layoutRevisionMethodNames.add("isIconImage"); _layoutRevisionMethodNames.add("isInheritLookAndFeel"); _layoutRevisionMethodNames.add("setColorSchemeId"); _layoutRevisionMethodNames.add("setCss"); _layoutRevisionMethodNames.add("setDescription"); _layoutRevisionMethodNames.add("setDescriptionMap"); _layoutRevisionMethodNames.add("setEscapedModel"); _layoutRevisionMethodNames.add("setGroupId"); _layoutRevisionMethodNames.add("setIconImage"); _layoutRevisionMethodNames.add("setIconImageId"); _layoutRevisionMethodNames.add("setKeywords"); _layoutRevisionMethodNames.add("setKeywordsMap"); _layoutRevisionMethodNames.add("setName"); _layoutRevisionMethodNames.add("setNameMap"); _layoutRevisionMethodNames.add("setRobots"); _layoutRevisionMethodNames.add("setRobotsMap"); _layoutRevisionMethodNames.add("setThemeId"); _layoutRevisionMethodNames.add("setTitle"); _layoutRevisionMethodNames.add("setTitleMap"); _layoutRevisionMethodNames.add("setTypeSettings"); _layoutRevisionMethodNames.add("setTypeSettingsProperties"); } private final Layout _layout; private LayoutRevision _layoutRevision; }