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