001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.model;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.ParamUtil;
021    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
022    import com.liferay.portal.kernel.util.ProxyUtil;
023    import com.liferay.portal.kernel.util.ReflectionUtil;
024    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
025    import com.liferay.portal.service.ServiceContext;
026    import com.liferay.portal.service.ServiceContextThreadLocal;
027    
028    import java.io.Serializable;
029    
030    import java.lang.reflect.InvocationHandler;
031    import java.lang.reflect.InvocationTargetException;
032    import java.lang.reflect.Method;
033    
034    import java.util.HashSet;
035    import java.util.Set;
036    
037    /**
038     * @author Julio Camarero
039     * @author Brian Wing Shun Chan
040     */
041    public class LayoutSetStagingHandler
042            implements InvocationHandler, Serializable {
043    
044            public LayoutSetStagingHandler(LayoutSet layoutSet) {
045                    _layoutSet = layoutSet;
046    
047                    try {
048                            _layoutSetBranch = _getLayoutSetBranch(layoutSet);
049                    }
050                    catch (Exception e) {
051                            _log.error(e, e);
052    
053                            throw new IllegalStateException(e);
054                    }
055            }
056    
057            public LayoutSet getLayoutSet() {
058                    return _layoutSet;
059            }
060    
061            public LayoutSetBranch getLayoutSetBranch() {
062                    return _layoutSetBranch;
063            }
064    
065            @Override
066            public Object invoke(Object proxy, Method method, Object[] arguments)
067                    throws Throwable {
068    
069                    try {
070                            if (_layoutSetBranch == null) {
071                                    return method.invoke(_layoutSet, arguments);
072                            }
073    
074                            String methodName = method.getName();
075    
076                            if (methodName.equals("toEscapedModel")) {
077                                    if (_layoutSet.isEscapedModel()) {
078                                            return this;
079                                    }
080    
081                                    return _toEscapedModel();
082                            }
083    
084                            if (methodName.equals("clone")) {
085                                    return _clone();
086                            }
087    
088                            Object bean = _layoutSet;
089    
090                            if (_layoutSetBranchMethodNames.contains(methodName)) {
091                                    try {
092                                            Class<?> layoutSetBranchClass = _layoutSetBranch.getClass();
093    
094                                            method = layoutSetBranchClass.getMethod(
095                                                    methodName,
096                                                    ReflectionUtil.getParameterTypes(arguments));
097    
098                                            bean = _layoutSetBranch;
099                                    }
100                                    catch (NoSuchMethodException nsme) {
101                                            _log.error(nsme, nsme);
102                                    }
103                            }
104    
105                            return method.invoke(bean, arguments);
106                    }
107                    catch (InvocationTargetException ite) {
108                            throw ite.getTargetException();
109                    }
110            }
111    
112            public void setLayoutSetBranch(LayoutSetBranch layoutSetBranch) {
113                    _layoutSetBranch = layoutSetBranch;
114            }
115    
116            private Object _clone() {
117                    return ProxyUtil.newProxyInstance(
118                            PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
119                            new LayoutSetStagingHandler(_layoutSet));
120            }
121    
122            private LayoutSetBranch _getLayoutSetBranch(LayoutSet layoutSet)
123                    throws PortalException {
124    
125                    ServiceContext serviceContext =
126                            ServiceContextThreadLocal.getServiceContext();
127    
128                    if (serviceContext == null) {
129                            return null;
130                    }
131    
132                    long layoutSetBranchId = ParamUtil.getLong(
133                            serviceContext, "layoutSetBranchId");
134    
135                    if (layoutSetBranchId > 0) {
136                            return LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
137                                    layoutSetBranchId);
138                    }
139    
140                    if (serviceContext.isSignedIn()) {
141                            return LayoutSetBranchLocalServiceUtil.getUserLayoutSetBranch(
142                                    serviceContext.getUserId(), layoutSet.getGroupId(),
143                                    layoutSet.isPrivateLayout(), layoutSet.getLayoutSetId(),
144                                    layoutSetBranchId);
145                    }
146    
147                    return LayoutSetBranchLocalServiceUtil.getMasterLayoutSetBranch(
148                            layoutSet.getGroupId(), layoutSet.isPrivateLayout());
149            }
150    
151            private Object _toEscapedModel() {
152                    return ProxyUtil.newProxyInstance(
153                            PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
154                            new LayoutSetStagingHandler(_layoutSet.toEscapedModel()));
155            }
156    
157            private static final Log _log = LogFactoryUtil.getLog(
158                    LayoutSetStagingHandler.class);
159    
160            private static final Set<String> _layoutSetBranchMethodNames =
161                    new HashSet<>();
162    
163            static {
164                    _layoutSetBranchMethodNames.add("getColorScheme");
165                    _layoutSetBranchMethodNames.add("getColorSchemeId");
166                    _layoutSetBranchMethodNames.add("getCss");
167                    _layoutSetBranchMethodNames.add("getLayoutSetPrototypeLinkEnabled");
168                    _layoutSetBranchMethodNames.add("getLayoutSetPrototypeUuid");
169                    _layoutSetBranchMethodNames.add("getLogo");
170                    _layoutSetBranchMethodNames.add("getLogoId");
171                    _layoutSetBranchMethodNames.add("getSettings");
172                    _layoutSetBranchMethodNames.add("getTheme");
173                    _layoutSetBranchMethodNames.add("getThemeId");
174                    _layoutSetBranchMethodNames.add("getWapColorScheme");
175                    _layoutSetBranchMethodNames.add("getWapColorSchemeId");
176                    _layoutSetBranchMethodNames.add("getWapTheme");
177                    _layoutSetBranchMethodNames.add("getWapThemeId");
178                    _layoutSetBranchMethodNames.add("getSettingsProperties");
179                    _layoutSetBranchMethodNames.add("getSettings");
180                    _layoutSetBranchMethodNames.add("getStagingLogoId");
181                    _layoutSetBranchMethodNames.add("getThemeSetting");
182                    _layoutSetBranchMethodNames.add("getSettingsProperty");
183                    _layoutSetBranchMethodNames.add("isLayoutSetPrototypeLinkActive");
184                    _layoutSetBranchMethodNames.add("isEscapedModel");
185                    _layoutSetBranchMethodNames.add("isLogo");
186                    _layoutSetBranchMethodNames.add("setColorSchemeId");
187                    _layoutSetBranchMethodNames.add("setCss");
188                    _layoutSetBranchMethodNames.add("setLayoutSetPrototypeLinkEnabled");
189                    _layoutSetBranchMethodNames.add("setLayoutSetPrototypeUuid");
190                    _layoutSetBranchMethodNames.add("setEscapedModel");
191                    _layoutSetBranchMethodNames.add("setLogo");
192                    _layoutSetBranchMethodNames.add("setLogoId");
193                    _layoutSetBranchMethodNames.add("setSettings");
194                    _layoutSetBranchMethodNames.add("setSettingsProperties");
195                    _layoutSetBranchMethodNames.add("setThemeId");
196                    _layoutSetBranchMethodNames.add("setWapColorSchemeId");
197                    _layoutSetBranchMethodNames.add("setWapThemeId");
198            }
199    
200            private final LayoutSet _layoutSet;
201            private LayoutSetBranch _layoutSetBranch;
202    
203    }