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