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.model;
016    
017    import com.liferay.portal.NoSuchLayoutBranchException;
018    import com.liferay.portal.NoSuchLayoutRevisionException;
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.StagingUtil;
024    import com.liferay.portal.kernel.util.ParamUtil;
025    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
026    import com.liferay.portal.kernel.util.ProxyUtil;
027    import com.liferay.portal.kernel.util.ReflectionUtil;
028    import com.liferay.portal.kernel.workflow.WorkflowConstants;
029    import com.liferay.portal.service.LayoutBranchLocalServiceUtil;
030    import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
031    import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
032    import com.liferay.portal.service.ServiceContext;
033    import com.liferay.portal.service.ServiceContextThreadLocal;
034    import com.liferay.portal.service.UserLocalServiceUtil;
035    import com.liferay.portal.util.LayoutTypePortletFactoryUtil;
036    
037    import java.lang.reflect.InvocationHandler;
038    import java.lang.reflect.InvocationTargetException;
039    import java.lang.reflect.Method;
040    
041    import java.util.HashSet;
042    import java.util.List;
043    import java.util.Set;
044    
045    /**
046     * @author Raymond Augé
047     * @author Brian Wing Shun Chan
048     */
049    public class LayoutStagingHandler implements InvocationHandler {
050    
051            public LayoutStagingHandler(Layout layout) {
052                    this(layout, null);
053            }
054    
055            public Layout getLayout() {
056                    return _layout;
057            }
058    
059            public LayoutRevision getLayoutRevision() {
060                    return _layoutRevision;
061            }
062    
063            public Object invoke(Object proxy, Method method, Object[] args)
064                    throws Throwable {
065    
066                    try {
067                            if (_layoutRevision == null) {
068                                    return method.invoke(_layout, args);
069                            }
070    
071                            String methodName = method.getName();
072    
073                            if (methodName.equals("getLayoutType")) {
074                                    return _getLayoutType();
075                            }
076                            else if (methodName.equals("toEscapedModel")) {
077                                    if (_layout.isEscapedModel()) {
078                                            return this;
079                                    }
080    
081                                    return _toEscapedModel();
082                            }
083    
084                            if (methodName.equals("clone")) {
085                                    return _clone();
086                            }
087    
088                            Object bean = _layout;
089    
090                            if (_layoutRevisionMethodNames.contains(methodName)) {
091                                    try {
092                                            Class<?> layoutRevisionClass = _layoutRevision.getClass();
093    
094                                            method = layoutRevisionClass.getMethod(
095                                                    methodName, ReflectionUtil.getParameterTypes(args));
096    
097                                            bean = _layoutRevision;
098                                    }
099                                    catch (NoSuchMethodException nsme) {
100                                            _log.error(nsme, nsme);
101                                    }
102                            }
103    
104                            return method.invoke(bean, args);
105                    }
106                    catch (InvocationTargetException ite) {
107                            throw ite.getTargetException();
108                    }
109            }
110    
111            public void setLayoutRevision(LayoutRevision layoutRevision) {
112                    _layoutRevision = layoutRevision;
113            }
114    
115            private LayoutStagingHandler(
116                    Layout layout, LayoutRevision layoutRevision) {
117    
118                    _layout = layout;
119    
120                    try {
121                            _layoutRevision = _getLayoutRevision(layout, layoutRevision);
122                    }
123                    catch (Exception e) {
124                            _log.error(e, e);
125    
126                            throw new IllegalStateException(e);
127                    }
128            }
129    
130            private Object _clone() {
131                    return ProxyUtil.newProxyInstance(
132                            PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
133                            new LayoutStagingHandler(_layout, _layoutRevision));
134            }
135    
136            private LayoutRevision _getLayoutRevision(
137                            Layout layout, LayoutRevision layoutRevision)
138                    throws PortalException, SystemException {
139    
140                    if (layoutRevision != null) {
141                            return layoutRevision;
142                    }
143    
144                    ServiceContext serviceContext =
145                            ServiceContextThreadLocal.getServiceContext();
146    
147                    if (!serviceContext.isSignedIn()) {
148                            return layoutRevision;
149                    }
150    
151                    long layoutSetBranchId = ParamUtil.getLong(
152                            serviceContext, "layoutSetBranchId");
153    
154                    LayoutSetBranch layoutSetBranch =
155                            LayoutSetBranchLocalServiceUtil.getUserLayoutSetBranch(
156                                    serviceContext.getUserId(), layout.getGroupId(),
157                                    layout.isPrivateLayout(), layoutSetBranchId);
158    
159                    layoutSetBranchId = layoutSetBranch.getLayoutSetBranchId();
160    
161                    long layoutRevisionId = ParamUtil.getLong(
162                            serviceContext, "layoutRevisionId");
163    
164                    if (layoutSetBranchId > 0) {
165                            if (layoutRevisionId <= 0) {
166                                    User user = UserLocalServiceUtil.getUser(
167                                            serviceContext.getUserId());
168    
169                                    layoutRevisionId = StagingUtil.getRecentLayoutRevisionId(
170                                            user, layoutSetBranchId, layout.getPlid());
171    
172                                    if (layoutRevisionId > 0) {
173                                            try {
174                                                    layoutRevision =
175                                                            LayoutRevisionLocalServiceUtil.getLayoutRevision(
176                                                                    layoutRevisionId);
177    
178                                                    if (layoutRevision.getStatus() !=
179                                                                    WorkflowConstants.STATUS_INACTIVE) {
180    
181                                                            return layoutRevision;
182                                                    }
183    
184                                                    StagingUtil.setRecentLayoutRevisionId(
185                                                            user, layoutSetBranchId, layout.getPlid(),
186                                                            LayoutRevisionConstants.
187                                                                    DEFAULT_PARENT_LAYOUT_REVISION_ID);
188    
189                                                    layoutRevisionId =
190                                                            StagingUtil.getRecentLayoutRevisionId(
191                                                                    user, layoutSetBranchId, layout.getPlid());
192                                            }
193                                            catch (NoSuchLayoutRevisionException nslre) {
194                                            }
195                                    }
196                            }
197    
198                            try {
199                                    return LayoutRevisionLocalServiceUtil.getLayoutRevision(
200                                            layoutSetBranchId, layout.getPlid(), true);
201                            }
202                            catch (NoSuchLayoutRevisionException nslre) {
203                                    List<LayoutRevision> layoutRevisions =
204                                            LayoutRevisionLocalServiceUtil.getChildLayoutRevisions(
205                                                    layoutSetBranchId,
206                                                    LayoutRevisionConstants.
207                                                            DEFAULT_PARENT_LAYOUT_REVISION_ID,
208                                                    layout.getPlid());
209    
210                                    if (!layoutRevisions.isEmpty()) {
211                                            return layoutRevisions.get(0);
212                                    }
213                            }
214                    }
215    
216                    if (layoutRevisionId > 0) {
217                            try {
218                                    return LayoutRevisionLocalServiceUtil.getLayoutRevision(
219                                            layoutRevisionId);
220                            }
221                            catch (NoSuchLayoutRevisionException nslre) {
222                            }
223                    }
224    
225                    LayoutBranch layoutBranch = null;
226    
227                    try {
228                            layoutBranch = LayoutBranchLocalServiceUtil.getMasterLayoutBranch(
229                                    layoutSetBranchId, layout.getPlid());
230                    }
231                    catch (NoSuchLayoutBranchException nslbe) {
232                            layoutBranch = LayoutBranchLocalServiceUtil.addLayoutBranch(
233                                    layoutSetBranchId, layout.getPlid(),
234                                    LayoutBranchConstants.MASTER_BRANCH_NAME,
235                                    LayoutBranchConstants.MASTER_BRANCH_DESCRIPTION, true,
236                                    serviceContext);
237                    }
238    
239                    layoutRevision = LayoutRevisionLocalServiceUtil.addLayoutRevision(
240                            serviceContext.getUserId(), layoutSetBranchId,
241                            layoutBranch.getLayoutBranchId(),
242                            LayoutRevisionConstants.DEFAULT_PARENT_LAYOUT_REVISION_ID, false,
243                            layout.getPlid(), layout.isPrivateLayout(), layout.getName(),
244                            layout.getTitle(), layout.getDescription(), layout.getKeywords(),
245                            layout.getRobots(), layout.getTypeSettings(), layout.getIconImage(),
246                            layout.getIconImageId(), layout.getThemeId(),
247                            layout.getColorSchemeId(), layout.getWapThemeId(),
248                            layout.getWapColorSchemeId(), layout.getCss(), serviceContext);
249    
250                    boolean explicitCreation = ParamUtil.getBoolean(
251                            serviceContext, "explicitCreation");
252    
253                    if (!explicitCreation) {
254                            LayoutRevisionLocalServiceUtil.updateStatus(
255                                    serviceContext.getUserId(),
256                                    layoutRevision.getLayoutRevisionId(),
257                                    WorkflowConstants.STATUS_INCOMPLETE, serviceContext);
258                    }
259    
260                    return layoutRevision;
261            }
262    
263            private LayoutType _getLayoutType() {
264                    return LayoutTypePortletFactoryUtil.create(
265                            (Layout)ProxyUtil.newProxyInstance(
266                                    PortalClassLoaderUtil.getClassLoader(),
267                                    new Class[] {Layout.class},
268                                    new LayoutStagingHandler(_layout, _layoutRevision)));
269            }
270    
271            private Object _toEscapedModel() {
272                    return ProxyUtil.newProxyInstance(
273                            PortalClassLoaderUtil.getClassLoader(),
274                            new Class[] {Layout.class},
275                            new LayoutStagingHandler(
276                                    _layout.toEscapedModel(), _layoutRevision.toEscapedModel()));
277            }
278    
279            private static Log _log = LogFactoryUtil.getLog(LayoutStagingHandler.class);
280    
281            private static Set<String> _layoutRevisionMethodNames =
282                    new HashSet<String>();
283    
284            private Layout _layout;
285            private LayoutRevision _layoutRevision;
286    
287            static {
288                    _layoutRevisionMethodNames.add("getColorScheme");
289                    _layoutRevisionMethodNames.add("getColorSchemeId");
290                    _layoutRevisionMethodNames.add("getCss");
291                    _layoutRevisionMethodNames.add("getCssText");
292                    _layoutRevisionMethodNames.add("getDescription");
293                    _layoutRevisionMethodNames.add("getHTMLTitle");
294                    _layoutRevisionMethodNames.add("getIconImage");
295                    _layoutRevisionMethodNames.add("getIconImageId");
296                    _layoutRevisionMethodNames.add("getKeywords");
297                    _layoutRevisionMethodNames.add("getName");
298                    _layoutRevisionMethodNames.add("getRobots");
299                    _layoutRevisionMethodNames.add("getTheme");
300                    _layoutRevisionMethodNames.add("getThemeId");
301                    _layoutRevisionMethodNames.add("getTitle");
302                    _layoutRevisionMethodNames.add("getTypeSettings");
303                    _layoutRevisionMethodNames.add("getTypeSettingsProperties");
304                    _layoutRevisionMethodNames.add("getWapColorScheme");
305                    _layoutRevisionMethodNames.add("getWapColorSchemeId");
306                    _layoutRevisionMethodNames.add("getWapTheme");
307                    _layoutRevisionMethodNames.add("getWapThemeId");
308                    _layoutRevisionMethodNames.add("isEscapedModel");
309                    _layoutRevisionMethodNames.add("isIconImage");
310                    _layoutRevisionMethodNames.add("isInheritLookAndFeel");
311                    _layoutRevisionMethodNames.add("isInheritWapLookAndFeel");
312                    _layoutRevisionMethodNames.add("setColorSchemeId");
313                    _layoutRevisionMethodNames.add("setCss");
314                    _layoutRevisionMethodNames.add("setDescription");
315                    _layoutRevisionMethodNames.add("setDescriptionMap");
316                    _layoutRevisionMethodNames.add("setEscapedModel");
317                    _layoutRevisionMethodNames.add("setIconImage");
318                    _layoutRevisionMethodNames.add("setIconImageId");
319                    _layoutRevisionMethodNames.add("setKeywords");
320                    _layoutRevisionMethodNames.add("setKeywordsMap");
321                    _layoutRevisionMethodNames.add("setName");
322                    _layoutRevisionMethodNames.add("setNameMap");
323                    _layoutRevisionMethodNames.add("setRobots");
324                    _layoutRevisionMethodNames.add("setRobotsMap");
325                    _layoutRevisionMethodNames.add("setThemeId");
326                    _layoutRevisionMethodNames.add("setTitle");
327                    _layoutRevisionMethodNames.add("setTitleMap");
328                    _layoutRevisionMethodNames.add("setTypeSettings");
329                    _layoutRevisionMethodNames.add("setTypeSettingsProperties");
330                    _layoutRevisionMethodNames.add("setWapColorSchemeId");
331                    _layoutRevisionMethodNames.add("setWapThemeId");
332            }
333    
334    }